@sideboard-ai/core 0.1.127 → 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-DLM5LSQW.js → chunk-SMWJAE74.js} +109 -16
- package/dist/{chunk-T7KJQJAX.js → chunk-VFXZTSAD.js} +111 -17
- 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 +343 -106
- package/dist/index.d.cts +54 -4
- package/dist/index.d.ts +54 -4
- package/dist/index.js +64 -72
- package/dist/mcp/run-stdio.cjs +301 -76
- package/dist/mcp/run-stdio.js +34 -39
- package/dist/oauth-43NNH6C6.js +12 -0
- package/dist/oauth-FT7EL2PY.js +10 -0
- package/dist/{orchestrator-6GUCE4LY.js → orchestrator-5TN2DJWO.js} +5 -4
- package/dist/{orchestrator-3JLPPTCF.js → orchestrator-JA65XKB6.js} +4 -3
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6780,11 +6780,40 @@ function humanizeAgentFailDetail(detail) {
|
|
|
6780
6780
|
}
|
|
6781
6781
|
function turnFailChatText(opts) {
|
|
6782
6782
|
const chat = opts.assistantText.trim();
|
|
6783
|
-
if (
|
|
6784
|
-
if (opts.exitCode === 0) return "";
|
|
6783
|
+
if (opts.exitCode === 0) return chat;
|
|
6785
6784
|
const detail = opts.detail.trim();
|
|
6786
|
-
|
|
6787
|
-
|
|
6785
|
+
const fail4 = detail ? humanizeAgentFailDetail(detail) : formatTurnExitError(opts.exitCode ?? 1, "");
|
|
6786
|
+
if (!chat) return fail4;
|
|
6787
|
+
const failCore = fail4.replace(/^exit\s*\d+:\s*/i, "").trim();
|
|
6788
|
+
if (looksLikeAgentFailureMessage(chat) || failCore && chat.includes(failCore) || chat.includes(fail4)) {
|
|
6789
|
+
return chat;
|
|
6790
|
+
}
|
|
6791
|
+
return `${chat}
|
|
6792
|
+
|
|
6793
|
+
${fail4}`;
|
|
6794
|
+
}
|
|
6795
|
+
function shouldFeedErrorBackToAgent(opts) {
|
|
6796
|
+
const detail = opts.detail.trim();
|
|
6797
|
+
const chat = (opts.assistantText ?? "").trim();
|
|
6798
|
+
if (looksLikeAgentFailureMessage(detail) || looksLikeAgentFailureMessage(chat)) {
|
|
6799
|
+
return false;
|
|
6800
|
+
}
|
|
6801
|
+
if (looksLikeInvalidAgentSession(detail) || looksLikeV8Oom(detail) || looksLikeRetryableRunnerCrash(detail)) {
|
|
6802
|
+
return true;
|
|
6803
|
+
}
|
|
6804
|
+
if (/without details|segfault|sig(?:segv|abrt|ill)|fatal error/i.test(detail)) {
|
|
6805
|
+
return true;
|
|
6806
|
+
}
|
|
6807
|
+
return !chat && (opts.partsCount ?? 0) === 0;
|
|
6808
|
+
}
|
|
6809
|
+
function formatAgentErrorContinuePrompt(detail) {
|
|
6810
|
+
const fail4 = humanizeAgentFailDetail(detail.trim()) || "the agent process exited without details";
|
|
6811
|
+
return [
|
|
6812
|
+
"The previous agent process ended before it finished. Error:",
|
|
6813
|
+
fail4,
|
|
6814
|
+
"",
|
|
6815
|
+
"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."
|
|
6816
|
+
].join("\n");
|
|
6788
6817
|
}
|
|
6789
6818
|
function formatTurnExitError(exitCode, stderrSummary) {
|
|
6790
6819
|
const code = exitCode ?? 1;
|
|
@@ -6814,6 +6843,8 @@ var init_error_detail = __esm({
|
|
|
6814
6843
|
|
|
6815
6844
|
// src/brightsy/config.ts
|
|
6816
6845
|
function brightsyConfigPath() {
|
|
6846
|
+
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
6847
|
+
if (override) return override;
|
|
6817
6848
|
return (0, import_node_path22.join)((0, import_node_os6.homedir)(), ".brightsy", "config.json");
|
|
6818
6849
|
}
|
|
6819
6850
|
function loadBrightsyConfig() {
|
|
@@ -6843,6 +6874,117 @@ var init_config = __esm({
|
|
|
6843
6874
|
}
|
|
6844
6875
|
});
|
|
6845
6876
|
|
|
6877
|
+
// src/http/fetch.ts
|
|
6878
|
+
function setHttpFetchImpl(fetchImpl) {
|
|
6879
|
+
injected = fetchImpl;
|
|
6880
|
+
}
|
|
6881
|
+
function formatFetchError(err, url) {
|
|
6882
|
+
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
6883
|
+
const cause = err.cause;
|
|
6884
|
+
let detail = "";
|
|
6885
|
+
if (cause instanceof Error) {
|
|
6886
|
+
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
6887
|
+
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
6888
|
+
} else if (cause != null) {
|
|
6889
|
+
detail = ` [${String(cause)}]`;
|
|
6890
|
+
}
|
|
6891
|
+
return `${err.message}${detail} (${url})`;
|
|
6892
|
+
}
|
|
6893
|
+
async function httpFetch(input, init) {
|
|
6894
|
+
const url = typeof input === "string" ? input : input.href;
|
|
6895
|
+
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
6896
|
+
try {
|
|
6897
|
+
return await fn(url, init);
|
|
6898
|
+
} catch (err) {
|
|
6899
|
+
throw new Error(formatFetchError(err, url));
|
|
6900
|
+
}
|
|
6901
|
+
}
|
|
6902
|
+
var injected;
|
|
6903
|
+
var init_fetch = __esm({
|
|
6904
|
+
"src/http/fetch.ts"() {
|
|
6905
|
+
"use strict";
|
|
6906
|
+
injected = null;
|
|
6907
|
+
}
|
|
6908
|
+
});
|
|
6909
|
+
|
|
6910
|
+
// src/brightsy/oauth.ts
|
|
6911
|
+
var oauth_exports = {};
|
|
6912
|
+
__export(oauth_exports, {
|
|
6913
|
+
brightsyAccessTokenNeedsRefresh: () => brightsyAccessTokenNeedsRefresh,
|
|
6914
|
+
ensureBrightsyLocalConfigFresh: () => ensureBrightsyLocalConfigFresh,
|
|
6915
|
+
refreshBrightsyAccessToken: () => refreshBrightsyAccessToken
|
|
6916
|
+
});
|
|
6917
|
+
function brightsyAccessTokenNeedsRefresh(expiresAt, now = Date.now()) {
|
|
6918
|
+
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt) || expiresAt <= 0) {
|
|
6919
|
+
return true;
|
|
6920
|
+
}
|
|
6921
|
+
return now >= expiresAt - REFRESH_SKEW_MS;
|
|
6922
|
+
}
|
|
6923
|
+
function applyGrant(current, grant) {
|
|
6924
|
+
return {
|
|
6925
|
+
access_token: grant.access_token,
|
|
6926
|
+
refresh_token: grant.refresh_token || current.refresh_token,
|
|
6927
|
+
expires_at: grant.expires_at ?? current.expires_at
|
|
6928
|
+
};
|
|
6929
|
+
}
|
|
6930
|
+
async function refreshBrightsyAccessToken(opts) {
|
|
6931
|
+
const endpoint = (opts.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
6932
|
+
const url = `${endpoint}/oauth/token`;
|
|
6933
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
6934
|
+
let res;
|
|
6935
|
+
try {
|
|
6936
|
+
res = await fetchImpl(url, {
|
|
6937
|
+
method: "POST",
|
|
6938
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
6939
|
+
body: new URLSearchParams({
|
|
6940
|
+
grant_type: "refresh_token",
|
|
6941
|
+
refresh_token: opts.refreshToken,
|
|
6942
|
+
client_id: opts.clientId || "brightsy-cli"
|
|
6943
|
+
})
|
|
6944
|
+
});
|
|
6945
|
+
} catch (err) {
|
|
6946
|
+
throw new Error(formatFetchError(err, url));
|
|
6947
|
+
}
|
|
6948
|
+
if (!res.ok) return null;
|
|
6949
|
+
const data = await res.json();
|
|
6950
|
+
if (!data.access_token) return null;
|
|
6951
|
+
return {
|
|
6952
|
+
access_token: data.access_token,
|
|
6953
|
+
refresh_token: data.refresh_token,
|
|
6954
|
+
expires_at: data.expires_in ? Date.now() + data.expires_in * 1e3 : void 0
|
|
6955
|
+
};
|
|
6956
|
+
}
|
|
6957
|
+
async function ensureBrightsyLocalConfigFresh(opts) {
|
|
6958
|
+
let cfg;
|
|
6959
|
+
try {
|
|
6960
|
+
cfg = loadBrightsyConfig();
|
|
6961
|
+
} catch {
|
|
6962
|
+
return null;
|
|
6963
|
+
}
|
|
6964
|
+
if (!cfg.refresh_token || !brightsyAccessTokenNeedsRefresh(cfg.expires_at)) {
|
|
6965
|
+
return cfg;
|
|
6966
|
+
}
|
|
6967
|
+
const grant = await refreshBrightsyAccessToken({
|
|
6968
|
+
endpoint: cfg.endpoint || "https://brightsy.ai",
|
|
6969
|
+
refreshToken: cfg.refresh_token,
|
|
6970
|
+
clientId: cfg.oauth_client_id,
|
|
6971
|
+
fetchImpl: opts?.fetchImpl
|
|
6972
|
+
});
|
|
6973
|
+
if (!grant) return cfg;
|
|
6974
|
+
const next = { ...cfg, ...applyGrant(cfg, grant) };
|
|
6975
|
+
saveBrightsyConfig(next);
|
|
6976
|
+
return next;
|
|
6977
|
+
}
|
|
6978
|
+
var REFRESH_SKEW_MS;
|
|
6979
|
+
var init_oauth = __esm({
|
|
6980
|
+
"src/brightsy/oauth.ts"() {
|
|
6981
|
+
"use strict";
|
|
6982
|
+
init_fetch();
|
|
6983
|
+
init_config();
|
|
6984
|
+
REFRESH_SKEW_MS = 6e4;
|
|
6985
|
+
}
|
|
6986
|
+
});
|
|
6987
|
+
|
|
6846
6988
|
// src/brightsy/accounts.ts
|
|
6847
6989
|
async function loadConnectedTeams() {
|
|
6848
6990
|
const { listConnectedBrightsyTeams: listConnectedBrightsyTeams2 } = await Promise.resolve().then(() => (init_connected_teams(), connected_teams_exports));
|
|
@@ -6873,6 +7015,10 @@ async function listBrightsyAccounts() {
|
|
|
6873
7015
|
}
|
|
6874
7016
|
async function getBrightsySession() {
|
|
6875
7017
|
try {
|
|
7018
|
+
const { ensureBrightsyLocalConfigFresh: ensureBrightsyLocalConfigFresh2 } = await Promise.resolve().then(() => (init_oauth(), oauth_exports));
|
|
7019
|
+
const { ensureConnectedBrightsyTeamTokens: ensureConnectedBrightsyTeamTokens2 } = await Promise.resolve().then(() => (init_connected_teams(), connected_teams_exports));
|
|
7020
|
+
await ensureBrightsyLocalConfigFresh2();
|
|
7021
|
+
await ensureConnectedBrightsyTeamTokens2();
|
|
6876
7022
|
loadBrightsyConfig();
|
|
6877
7023
|
const data = await runBrightsyTeamsJson([]);
|
|
6878
7024
|
const accounts = Array.isArray(data.teams) ? data.teams : [];
|
|
@@ -6993,7 +7139,6 @@ function applyConnectedTeamToCli(team) {
|
|
|
6993
7139
|
}
|
|
6994
7140
|
async function refreshTeamToken(team) {
|
|
6995
7141
|
if (!team.refresh_token) return team;
|
|
6996
|
-
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
6997
7142
|
const cfg = (() => {
|
|
6998
7143
|
try {
|
|
6999
7144
|
return loadBrightsyConfig();
|
|
@@ -7001,39 +7146,34 @@ async function refreshTeamToken(team) {
|
|
|
7001
7146
|
return null;
|
|
7002
7147
|
}
|
|
7003
7148
|
})();
|
|
7004
|
-
const
|
|
7005
|
-
|
|
7006
|
-
|
|
7007
|
-
|
|
7008
|
-
body: new URLSearchParams({
|
|
7009
|
-
grant_type: "refresh_token",
|
|
7010
|
-
refresh_token: team.refresh_token,
|
|
7011
|
-
client_id: clientId
|
|
7012
|
-
})
|
|
7149
|
+
const grant = await refreshBrightsyAccessToken({
|
|
7150
|
+
endpoint: team.endpoint || "https://brightsy.ai",
|
|
7151
|
+
refreshToken: team.refresh_token,
|
|
7152
|
+
clientId: cfg?.oauth_client_id
|
|
7013
7153
|
});
|
|
7014
|
-
if (!
|
|
7015
|
-
const data = await res.json();
|
|
7016
|
-
if (!data.access_token) return team;
|
|
7154
|
+
if (!grant) return team;
|
|
7017
7155
|
return {
|
|
7018
7156
|
...team,
|
|
7019
|
-
access_token:
|
|
7020
|
-
refresh_token:
|
|
7021
|
-
expires_at:
|
|
7157
|
+
access_token: grant.access_token,
|
|
7158
|
+
refresh_token: grant.refresh_token || team.refresh_token,
|
|
7159
|
+
expires_at: grant.expires_at ?? team.expires_at
|
|
7022
7160
|
};
|
|
7023
7161
|
}
|
|
7024
7162
|
async function ensureConnectedBrightsyTeamTokens() {
|
|
7163
|
+
await ensureBrightsyLocalConfigFresh().catch(() => null);
|
|
7025
7164
|
const teams = readStore4();
|
|
7026
7165
|
if (teams.length === 0) return [];
|
|
7027
7166
|
const next = [];
|
|
7028
7167
|
let changed = false;
|
|
7029
7168
|
for (const team of teams) {
|
|
7030
|
-
|
|
7031
|
-
if (!expired) {
|
|
7169
|
+
if (!team.refresh_token || !brightsyAccessTokenNeedsRefresh(team.expires_at)) {
|
|
7032
7170
|
next.push(team);
|
|
7033
7171
|
continue;
|
|
7034
7172
|
}
|
|
7035
7173
|
const refreshed = await refreshTeamToken(team);
|
|
7036
|
-
if (refreshed.access_token !== team.access_token
|
|
7174
|
+
if (refreshed.access_token !== team.access_token || refreshed.refresh_token !== team.refresh_token || refreshed.expires_at !== team.expires_at) {
|
|
7175
|
+
changed = true;
|
|
7176
|
+
}
|
|
7037
7177
|
next.push(refreshed);
|
|
7038
7178
|
}
|
|
7039
7179
|
if (changed) writeStore3(next);
|
|
@@ -7128,6 +7268,7 @@ var init_connected_teams = __esm({
|
|
|
7128
7268
|
init_paths();
|
|
7129
7269
|
init_accounts();
|
|
7130
7270
|
init_config();
|
|
7271
|
+
init_oauth();
|
|
7131
7272
|
}
|
|
7132
7273
|
});
|
|
7133
7274
|
|
|
@@ -8532,6 +8673,7 @@ function teamEnv(team) {
|
|
|
8532
8673
|
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
8533
8674
|
return {
|
|
8534
8675
|
BRIGHTSY_API_TOKEN: team.access_token,
|
|
8676
|
+
...team.refresh_token ? { BRIGHTSY_REFRESH_TOKEN: team.refresh_token } : {},
|
|
8535
8677
|
BRIGHTSY_ACCOUNT_ID: team.id,
|
|
8536
8678
|
BRIGHTSY_API_URL: endpoint
|
|
8537
8679
|
};
|
|
@@ -8818,10 +8960,15 @@ var init_types = __esm({
|
|
|
8818
8960
|
|
|
8819
8961
|
// src/agents/claude.ts
|
|
8820
8962
|
async function loadMcpServers() {
|
|
8963
|
+
if (mcpListCache && Date.now() - mcpListCache.at < 3e4) {
|
|
8964
|
+
return mcpListCache.servers;
|
|
8965
|
+
}
|
|
8821
8966
|
const claude = resolveClaudeExecutable();
|
|
8822
8967
|
const mcpText = await run(claude, ["mcp", "list"], { reject: false });
|
|
8823
|
-
|
|
8968
|
+
const servers = parseMcpList(`${mcpText.stdout}
|
|
8824
8969
|
${mcpText.stderr}`);
|
|
8970
|
+
mcpListCache = { at: Date.now(), servers };
|
|
8971
|
+
return servers;
|
|
8825
8972
|
}
|
|
8826
8973
|
function usageFromClaude(usage) {
|
|
8827
8974
|
if (!usage) return null;
|
|
@@ -9035,7 +9182,7 @@ function parseIssuesJson(raw) {
|
|
|
9035
9182
|
}
|
|
9036
9183
|
return [];
|
|
9037
9184
|
}
|
|
9038
|
-
var import_node_fs25, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, claudeAdapter;
|
|
9185
|
+
var import_node_fs25, BASE_ALLOWED_TOOLS, CLAUDE_PRINT_BG_WAIT_CEILING_MS, CLAUDE_CHROME_ALLOWED_TOOLS, CLAUDE_PROMPT_ARG_MAX, mcpListCache, claudeAdapter;
|
|
9039
9186
|
var init_claude = __esm({
|
|
9040
9187
|
"src/agents/claude.ts"() {
|
|
9041
9188
|
"use strict";
|
|
@@ -9073,6 +9220,7 @@ var init_claude = __esm({
|
|
|
9073
9220
|
"Skill(claude-in-chrome)"
|
|
9074
9221
|
];
|
|
9075
9222
|
CLAUDE_PROMPT_ARG_MAX = 2e5;
|
|
9223
|
+
mcpListCache = null;
|
|
9076
9224
|
claudeAdapter = {
|
|
9077
9225
|
kind: "claude",
|
|
9078
9226
|
async detect() {
|
|
@@ -10451,10 +10599,13 @@ var init_opencode = __esm({
|
|
|
10451
10599
|
const part = obj.part;
|
|
10452
10600
|
const id = part?.tool_use_id ?? part?.id ?? obj.tool_use_id ?? obj.id;
|
|
10453
10601
|
if (!id) return null;
|
|
10602
|
+
const flagged = obj.isError === true || obj.is_error === true;
|
|
10603
|
+
const errText2 = formatUnknownDetail(obj.error);
|
|
10454
10604
|
return {
|
|
10455
10605
|
type: "tool_result",
|
|
10456
10606
|
id,
|
|
10457
|
-
content: part?.output ?? part?.content ?? obj.output ?? obj.content
|
|
10607
|
+
content: part?.output ?? part?.content ?? obj.output ?? obj.content ?? (errText2 || void 0),
|
|
10608
|
+
isError: flagged || Boolean(errText2)
|
|
10458
10609
|
};
|
|
10459
10610
|
}
|
|
10460
10611
|
if (obj.type === "step_finish" || obj.type === "step-finish") {
|
|
@@ -12929,7 +13080,48 @@ function isMergedPrState(prUrl, prState) {
|
|
|
12929
13080
|
if (!prUrl?.trim()) return false;
|
|
12930
13081
|
return (prState ?? "").trim().toUpperCase() === "MERGED";
|
|
12931
13082
|
}
|
|
12932
|
-
function
|
|
13083
|
+
function groupCreatedAt(group) {
|
|
13084
|
+
let min = group[0]?.createdAt ?? "";
|
|
13085
|
+
for (const t of group) {
|
|
13086
|
+
if (t.createdAt && t.createdAt < min) min = t.createdAt;
|
|
13087
|
+
}
|
|
13088
|
+
return min;
|
|
13089
|
+
}
|
|
13090
|
+
function groupUpdatedAt(group) {
|
|
13091
|
+
let max = group[0]?.updatedAt ?? "";
|
|
13092
|
+
for (const t of group) {
|
|
13093
|
+
if (t.updatedAt && t.updatedAt > max) max = t.updatedAt;
|
|
13094
|
+
}
|
|
13095
|
+
return max;
|
|
13096
|
+
}
|
|
13097
|
+
function sortThreadsInWorktree(list) {
|
|
13098
|
+
return [...list].sort((a, b) => {
|
|
13099
|
+
const created = a.createdAt.localeCompare(b.createdAt);
|
|
13100
|
+
if (created !== 0) return created;
|
|
13101
|
+
return a.id.localeCompare(b.id);
|
|
13102
|
+
});
|
|
13103
|
+
}
|
|
13104
|
+
function compareWorktreeGroups(a, b, mode, labelOf) {
|
|
13105
|
+
if (mode === "name") {
|
|
13106
|
+
const named = (labelOf?.(a) ?? a[0]?.id ?? "").localeCompare(
|
|
13107
|
+
labelOf?.(b) ?? b[0]?.id ?? "",
|
|
13108
|
+
void 0,
|
|
13109
|
+
{ sensitivity: "base" }
|
|
13110
|
+
);
|
|
13111
|
+
if (named !== 0) return named;
|
|
13112
|
+
} else if (mode === "activity") {
|
|
13113
|
+
const activity = groupUpdatedAt(b).localeCompare(groupUpdatedAt(a));
|
|
13114
|
+
if (activity !== 0) return activity;
|
|
13115
|
+
} else {
|
|
13116
|
+
const created = groupCreatedAt(b).localeCompare(groupCreatedAt(a));
|
|
13117
|
+
if (created !== 0) return created;
|
|
13118
|
+
}
|
|
13119
|
+
return (a[0]?.id ?? "").localeCompare(b[0]?.id ?? "");
|
|
13120
|
+
}
|
|
13121
|
+
function defaultWorktreeGroupLabel(group) {
|
|
13122
|
+
return worktreeDisplayLabelForGroup(group);
|
|
13123
|
+
}
|
|
13124
|
+
function groupHomeBoardWorktrees(threads, sort = DEFAULT_WORKTREE_SORT, labelOf = defaultWorktreeGroupLabel) {
|
|
12933
13125
|
const map = /* @__PURE__ */ new Map();
|
|
12934
13126
|
for (const t of threads) {
|
|
12935
13127
|
const key = normalizeWorktreePath(t.worktreePath);
|
|
@@ -12937,7 +13129,7 @@ function groupHomeBoardWorktrees(threads) {
|
|
|
12937
13129
|
list.push(t);
|
|
12938
13130
|
map.set(key, list);
|
|
12939
13131
|
}
|
|
12940
|
-
return [...map.values()].map((list) => list.sort((a, b) =>
|
|
13132
|
+
return [...map.values()].map((list) => sortThreadsInWorktree(list)).sort((a, b) => compareWorktreeGroups(a, b, sort, labelOf));
|
|
12941
13133
|
}
|
|
12942
13134
|
function classifyWorktreeColumn(group) {
|
|
12943
13135
|
if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
|
|
@@ -13243,8 +13435,7 @@ function assembleHomeBoard(input) {
|
|
|
13243
13435
|
const kind = input.kind ?? "all";
|
|
13244
13436
|
const limit = Math.max(1, input.limit ?? BOARD_PAGE_SIZE);
|
|
13245
13437
|
const wsName = input.workspaceName ?? (() => "");
|
|
13246
|
-
const
|
|
13247
|
-
const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t)).sort(byUpdated);
|
|
13438
|
+
const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t));
|
|
13248
13439
|
const columns = emptyColumns();
|
|
13249
13440
|
const hidden = emptyHidden();
|
|
13250
13441
|
const totals = {
|
|
@@ -13299,7 +13490,7 @@ function assembleHomeBoard(input) {
|
|
|
13299
13490
|
}
|
|
13300
13491
|
return { columns, hidden, totals };
|
|
13301
13492
|
}
|
|
13302
|
-
var GLOBAL_WORKSPACE_ID2, BOARD_COLUMN_DEFS, HOME_BOARD_CACHE_TTL_MS, DEFAULTISH_BRANCH, BOARD_PAGE_SIZE, HOME_BOARD_AGENT_HINT;
|
|
13493
|
+
var GLOBAL_WORKSPACE_ID2, BOARD_COLUMN_DEFS, HOME_BOARD_CACHE_TTL_MS, DEFAULT_WORKTREE_SORT, DEFAULTISH_BRANCH, BOARD_PAGE_SIZE, HOME_BOARD_AGENT_HINT;
|
|
13303
13494
|
var init_home_board = __esm({
|
|
13304
13495
|
"src/board/home-board.ts"() {
|
|
13305
13496
|
"use strict";
|
|
@@ -13312,6 +13503,7 @@ var init_home_board = __esm({
|
|
|
13312
13503
|
{ id: "done", title: "Merged" }
|
|
13313
13504
|
];
|
|
13314
13505
|
HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
|
|
13506
|
+
DEFAULT_WORKTREE_SORT = "created";
|
|
13315
13507
|
DEFAULTISH_BRANCH = /^(main|master|develop|development|trunk|default|head)$/;
|
|
13316
13508
|
BOARD_PAGE_SIZE = 40;
|
|
13317
13509
|
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.";
|
|
@@ -15868,7 +16060,8 @@ function formatArtifactDirective() {
|
|
|
15868
16060
|
"```html",
|
|
15869
16061
|
"<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
|
|
15870
16062
|
"```",
|
|
15871
|
-
"2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content \u2014 not both a fence and this tool for the same body.",
|
|
16063
|
+
"2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
|
|
16064
|
+
" type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
|
|
15872
16065
|
"CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
|
|
15873
16066
|
"3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
|
|
15874
16067
|
" - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
|
|
@@ -15883,7 +16076,7 @@ function formatArtifactDirective() {
|
|
|
15883
16076
|
].join("\n");
|
|
15884
16077
|
}
|
|
15885
16078
|
function formatUiReminder() {
|
|
15886
|
-
return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
|
|
16079
|
+
return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
|
|
15887
16080
|
}
|
|
15888
16081
|
function loadAgentInstructions(worktreePath, agent) {
|
|
15889
16082
|
const candidates = FILES_BY_AGENT[agent] ?? FILES_BY_AGENT.claude;
|
|
@@ -16399,6 +16592,11 @@ var init_orchestrator = __esm({
|
|
|
16399
16592
|
turnBaselines = /* @__PURE__ */ new Map();
|
|
16400
16593
|
/** Timers for orchestration session-quota auto-resume. */
|
|
16401
16594
|
quotaResumeTimers = /* @__PURE__ */ new Map();
|
|
16595
|
+
/**
|
|
16596
|
+
* Threads that already got a crash-continue turn. Cleared on a successful
|
|
16597
|
+
* finish or a user send so a later crash can recover again.
|
|
16598
|
+
*/
|
|
16599
|
+
crashContinued = /* @__PURE__ */ new Set();
|
|
16402
16600
|
maxConcurrent;
|
|
16403
16601
|
runningCount = 0;
|
|
16404
16602
|
constructor(opts) {
|
|
@@ -16612,6 +16810,29 @@ var init_orchestrator = __esm({
|
|
|
16612
16810
|
);
|
|
16613
16811
|
}
|
|
16614
16812
|
}
|
|
16813
|
+
/**
|
|
16814
|
+
* Cursor-style recovery: after a runner crash, feed the error back as the
|
|
16815
|
+
* next prompt so the same agent can continue instead of sitting on lastError.
|
|
16816
|
+
*/
|
|
16817
|
+
maybeEnqueueCrashContinue(threadId, opts) {
|
|
16818
|
+
if (this.crashContinued.has(threadId)) return;
|
|
16819
|
+
if (this.haltDrain.has(threadId)) return;
|
|
16820
|
+
if (!shouldFeedErrorBackToAgent({
|
|
16821
|
+
detail: opts.detail,
|
|
16822
|
+
assistantText: opts.assistantText,
|
|
16823
|
+
partsCount: opts.partsCount
|
|
16824
|
+
})) {
|
|
16825
|
+
return;
|
|
16826
|
+
}
|
|
16827
|
+
const thread = readThread(threadId);
|
|
16828
|
+
if (!thread || thread.status === "archived") return;
|
|
16829
|
+
this.crashContinued.add(threadId);
|
|
16830
|
+
const prompt = formatAgentErrorContinuePrompt(opts.detail);
|
|
16831
|
+
const queue = [prompt, ...thread.queue];
|
|
16832
|
+
updateThread(threadId, { queue });
|
|
16833
|
+
this.emit({ type: "queue_changed", threadId, queue });
|
|
16834
|
+
this.haltDrain.delete(threadId);
|
|
16835
|
+
}
|
|
16615
16836
|
getThreads(includeArchived = false) {
|
|
16616
16837
|
return listThreads({ includeArchived });
|
|
16617
16838
|
}
|
|
@@ -16711,15 +16932,20 @@ var init_orchestrator = __esm({
|
|
|
16711
16932
|
throw new Error(`Thread is archived: ${thread.id}`);
|
|
16712
16933
|
}
|
|
16713
16934
|
const queue = [...current.queue, prompt];
|
|
16935
|
+
this.crashContinued.delete(thread.id);
|
|
16714
16936
|
this.haltDrain.delete(thread.id);
|
|
16715
|
-
const
|
|
16937
|
+
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
16938
|
+
const patch = { queue };
|
|
16939
|
+
if (!inFlight) patch.status = "queued";
|
|
16716
16940
|
const pid = current.agentPid;
|
|
16717
16941
|
if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
|
|
16718
16942
|
patch.agentPid = null;
|
|
16719
16943
|
}
|
|
16720
16944
|
updateThread(thread.id, patch);
|
|
16721
16945
|
this.emit({ type: "queue_changed", threadId: thread.id, queue });
|
|
16722
|
-
|
|
16946
|
+
if (!inFlight) {
|
|
16947
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
16948
|
+
}
|
|
16723
16949
|
if (thisProcessShouldDrainAgentQueues()) {
|
|
16724
16950
|
void this.drainQueue(thread.id);
|
|
16725
16951
|
}
|
|
@@ -17040,7 +17266,7 @@ var init_orchestrator = __esm({
|
|
|
17040
17266
|
let parts = result.parts;
|
|
17041
17267
|
let usage = result.usage ?? void 0;
|
|
17042
17268
|
let exitCode = result.exitCode;
|
|
17043
|
-
if (this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
|
|
17269
|
+
if (!this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
|
|
17044
17270
|
const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
|
|
17045
17271
|
if (sessionId) {
|
|
17046
17272
|
const { recoverFinishedCursorRun: recoverFinishedCursorRun2 } = await Promise.resolve().then(() => (init_cursor_recover(), cursor_recover_exports));
|
|
@@ -17061,7 +17287,7 @@ var init_orchestrator = __esm({
|
|
|
17061
17287
|
}
|
|
17062
17288
|
let lastStderr = summarizeTurnStderr(stderrTail);
|
|
17063
17289
|
let detail = lastStderr || (exitCode !== 0 ? fallbackTurnFailDetail(assistantText) : "");
|
|
17064
|
-
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) &&
|
|
17290
|
+
if (exitCode !== 0 && !assistantText && parts.length === 0 && !this.stoppedTurns.has(threadId) && shouldRetryFailedAgentTurn(detail, {
|
|
17065
17291
|
hasSession: Boolean(this.requireThread(threadId).sessionId)
|
|
17066
17292
|
})) {
|
|
17067
17293
|
updateThread(threadId, { sessionId: null });
|
|
@@ -17157,7 +17383,11 @@ var init_orchestrator = __esm({
|
|
|
17157
17383
|
)) {
|
|
17158
17384
|
updateThread(threadId, { sessionId: null });
|
|
17159
17385
|
}
|
|
17160
|
-
|
|
17386
|
+
if (this.stoppedTurns.has(threadId)) {
|
|
17387
|
+
void syncThreadBranchFromGit(threadId).catch(() => void 0);
|
|
17388
|
+
} else {
|
|
17389
|
+
await syncThreadBranchFromGit(threadId);
|
|
17390
|
+
}
|
|
17161
17391
|
if (this.stoppedTurns.has(threadId)) {
|
|
17162
17392
|
const stopped = writeLiveStatus(threadId, "stopped");
|
|
17163
17393
|
if (stopped?.status === "stopped") {
|
|
@@ -17181,9 +17411,16 @@ var init_orchestrator = __esm({
|
|
|
17181
17411
|
});
|
|
17182
17412
|
}
|
|
17183
17413
|
this.emit({ type: "turn_finished", threadId, exitCode });
|
|
17184
|
-
if (exitCode
|
|
17414
|
+
if (exitCode === 0) {
|
|
17415
|
+
this.crashContinued.delete(threadId);
|
|
17416
|
+
} else {
|
|
17185
17417
|
const blob = [chatText, detail].filter(Boolean).join("\n");
|
|
17186
17418
|
void this.maybeHandleOrchestrationQuotaFailover(threadId, blob);
|
|
17419
|
+
this.maybeEnqueueCrashContinue(threadId, {
|
|
17420
|
+
detail: detail || failDetail,
|
|
17421
|
+
assistantText: chatText,
|
|
17422
|
+
partsCount: parts.length
|
|
17423
|
+
});
|
|
17187
17424
|
}
|
|
17188
17425
|
}
|
|
17189
17426
|
} catch (err) {
|
|
@@ -17203,6 +17440,11 @@ var init_orchestrator = __esm({
|
|
|
17203
17440
|
}
|
|
17204
17441
|
this.emit({ type: "turn_finished", threadId, exitCode: 1 });
|
|
17205
17442
|
void this.maybeHandleOrchestrationQuotaFailover(threadId, message);
|
|
17443
|
+
this.maybeEnqueueCrashContinue(threadId, {
|
|
17444
|
+
detail: message,
|
|
17445
|
+
assistantText: "",
|
|
17446
|
+
partsCount: 0
|
|
17447
|
+
});
|
|
17206
17448
|
}
|
|
17207
17449
|
} finally {
|
|
17208
17450
|
this.startingTurns.delete(threadId);
|
|
@@ -18304,6 +18546,7 @@ __export(index_exports, {
|
|
|
18304
18546
|
CONTEXT_MIN_MESSAGES: () => CONTEXT_MIN_MESSAGES,
|
|
18305
18547
|
CONVENTION_SETUP_RELPATHS: () => CONVENTION_SETUP_RELPATHS,
|
|
18306
18548
|
COORDINATOR_TOOL_PLAYBOOK: () => COORDINATOR_TOOL_PLAYBOOK,
|
|
18549
|
+
DEFAULT_WORKTREE_SORT: () => DEFAULT_WORKTREE_SORT,
|
|
18307
18550
|
FAMOUS_SOCCER_TEAMS: () => FAMOUS_SOCCER_TEAMS,
|
|
18308
18551
|
GITHUB_GIT_AUTH_MODES: () => GITHUB_GIT_AUTH_MODES,
|
|
18309
18552
|
GLOBAL_WORKSPACE_ID: () => GLOBAL_WORKSPACE_ID,
|
|
@@ -18385,6 +18628,7 @@ __export(index_exports, {
|
|
|
18385
18628
|
autoRenameBranchEnabled: () => autoRenameBranchEnabled,
|
|
18386
18629
|
autoRunAfterSetupEnabled: () => autoRunAfterSetupEnabled,
|
|
18387
18630
|
branchDisplayLabel: () => branchDisplayLabel,
|
|
18631
|
+
brightsyAccessTokenNeedsRefresh: () => brightsyAccessTokenNeedsRefresh,
|
|
18388
18632
|
brightsyAdapter: () => brightsyAdapter,
|
|
18389
18633
|
brightsyCloudConnectAgent: () => brightsyCloudConnectAgent,
|
|
18390
18634
|
brightsyCloudConnectEnabled: () => brightsyCloudConnectEnabled,
|
|
@@ -18471,7 +18715,9 @@ __export(index_exports, {
|
|
|
18471
18715
|
enrichPathWithNpmGlobalBin: () => enrichPathWithNpmGlobalBin,
|
|
18472
18716
|
enrichWorkspacesWithGithub: () => enrichWorkspacesWithGithub,
|
|
18473
18717
|
ensureAgentPath: () => ensureAgentPath,
|
|
18718
|
+
ensureBrightsyLocalConfigFresh: () => ensureBrightsyLocalConfigFresh,
|
|
18474
18719
|
ensureCloudCoordinator: () => ensureCloudCoordinator,
|
|
18720
|
+
ensureConnectedBrightsyTeamTokens: () => ensureConnectedBrightsyTeamTokens,
|
|
18475
18721
|
ensureGhPreferOrigin: () => ensureGhPreferOrigin,
|
|
18476
18722
|
ensureGlobalCoordinatorCwd: () => ensureGlobalCoordinatorCwd,
|
|
18477
18723
|
ensureReviewRequestFile: () => ensureReviewRequestFile,
|
|
@@ -18734,6 +18980,7 @@ __export(index_exports, {
|
|
|
18734
18980
|
readWorktreeInclude: () => readWorktreeInclude,
|
|
18735
18981
|
recordScheduleRun: () => recordScheduleRun,
|
|
18736
18982
|
recordSlackOutboundWatch: () => recordSlackOutboundWatch,
|
|
18983
|
+
refreshBrightsyAccessToken: () => refreshBrightsyAccessToken,
|
|
18737
18984
|
refreshGitHubAuth: () => refreshGitHubAuth,
|
|
18738
18985
|
registerPackagedUserMcpClients: () => registerPackagedUserMcpClients,
|
|
18739
18986
|
releaseCaffeinateHoldForThread: () => releaseCaffeinateHoldForThread,
|
|
@@ -18964,37 +19211,14 @@ async function refreshGitHubAuth() {
|
|
|
18964
19211
|
return getGitHubStatus();
|
|
18965
19212
|
}
|
|
18966
19213
|
|
|
18967
|
-
// src/
|
|
18968
|
-
|
|
18969
|
-
function setHttpFetchImpl(fetchImpl) {
|
|
18970
|
-
injected = fetchImpl;
|
|
18971
|
-
}
|
|
18972
|
-
function formatFetchError(err, url) {
|
|
18973
|
-
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
18974
|
-
const cause = err.cause;
|
|
18975
|
-
let detail = "";
|
|
18976
|
-
if (cause instanceof Error) {
|
|
18977
|
-
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
18978
|
-
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
18979
|
-
} else if (cause != null) {
|
|
18980
|
-
detail = ` [${String(cause)}]`;
|
|
18981
|
-
}
|
|
18982
|
-
return `${err.message}${detail} (${url})`;
|
|
18983
|
-
}
|
|
18984
|
-
async function httpFetch(input, init) {
|
|
18985
|
-
const url = typeof input === "string" ? input : input.href;
|
|
18986
|
-
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
18987
|
-
try {
|
|
18988
|
-
return await fn(url, init);
|
|
18989
|
-
} catch (err) {
|
|
18990
|
-
throw new Error(formatFetchError(err, url));
|
|
18991
|
-
}
|
|
18992
|
-
}
|
|
19214
|
+
// src/integrations/linear.ts
|
|
19215
|
+
init_fetch();
|
|
18993
19216
|
|
|
18994
19217
|
// src/integrations/linear-oauth.ts
|
|
18995
19218
|
var import_node_crypto9 = require("crypto");
|
|
18996
19219
|
var import_node_http = require("http");
|
|
18997
19220
|
init_app_settings();
|
|
19221
|
+
init_fetch();
|
|
18998
19222
|
|
|
18999
19223
|
// src/integrations/linear-app.ts
|
|
19000
19224
|
var BAKED_LINEAR_CLIENT_ID = "39a15abc7ea5bea17c47f47f85ff5fd0";
|
|
@@ -19010,7 +19234,7 @@ var LINEAR_TOKEN = "https://api.linear.app/oauth/token";
|
|
|
19010
19234
|
var LINEAR_REVOKE = "https://api.linear.app/oauth/revoke";
|
|
19011
19235
|
var LINEAR_GRAPHQL = "https://api.linear.app/graphql";
|
|
19012
19236
|
var LINEAR_OAUTH_SCOPES = "read,write";
|
|
19013
|
-
var
|
|
19237
|
+
var REFRESH_SKEW_MS2 = 5 * 6e4;
|
|
19014
19238
|
function linearOAuthCredentials() {
|
|
19015
19239
|
const settings = loadAppSettings();
|
|
19016
19240
|
const clientId = process.env.SIDEBOARD_LINEAR_CLIENT_ID?.trim() || settings.integrations.linearClientId?.trim() || BAKED_LINEAR_CLIENT_ID.trim();
|
|
@@ -19121,7 +19345,7 @@ async function getLinearAuthToken(settings = loadAppSettings()) {
|
|
|
19121
19345
|
const refresh = settings.integrations.linearRefreshToken?.trim() || "";
|
|
19122
19346
|
const expiresAt = settings.integrations.linearTokenExpiresAt ?? 0;
|
|
19123
19347
|
const apiKey = settings.integrations.linearApiKey?.trim() || "";
|
|
19124
|
-
if (access && (!refresh || Date.now() < expiresAt -
|
|
19348
|
+
if (access && (!refresh || Date.now() < expiresAt - REFRESH_SKEW_MS2)) {
|
|
19125
19349
|
return access;
|
|
19126
19350
|
}
|
|
19127
19351
|
if (refresh) {
|
|
@@ -19264,6 +19488,16 @@ async function disconnectLinear() {
|
|
|
19264
19488
|
|
|
19265
19489
|
// src/integrations/linear.ts
|
|
19266
19490
|
var LINEAR_GRAPHQL2 = "https://api.linear.app/graphql";
|
|
19491
|
+
var LIST_ISSUE_FIELDS = `
|
|
19492
|
+
id
|
|
19493
|
+
identifier
|
|
19494
|
+
title
|
|
19495
|
+
url
|
|
19496
|
+
assignee { id name }
|
|
19497
|
+
team { id key }
|
|
19498
|
+
labels(first: 10) { nodes { name } }
|
|
19499
|
+
cycle { name number startsAt endsAt completedAt }
|
|
19500
|
+
`;
|
|
19267
19501
|
var ISSUE_FIELDS = `
|
|
19268
19502
|
id
|
|
19269
19503
|
identifier
|
|
@@ -19273,9 +19507,9 @@ var ISSUE_FIELDS = `
|
|
|
19273
19507
|
priority
|
|
19274
19508
|
state { id name type }
|
|
19275
19509
|
assignee { id name }
|
|
19276
|
-
team { id key name states { nodes { id name type } } }
|
|
19277
|
-
labels { nodes { name } }
|
|
19278
|
-
cycle {
|
|
19510
|
+
team { id key name states(first: 50) { nodes { id name type } } }
|
|
19511
|
+
labels(first: 50) { nodes { name } }
|
|
19512
|
+
cycle { name number startsAt endsAt completedAt }
|
|
19279
19513
|
`;
|
|
19280
19514
|
var ASSIGNED_ISSUES_QUERY = `
|
|
19281
19515
|
query SideboardAssignedIssues($first: Int!) {
|
|
@@ -19287,7 +19521,7 @@ query SideboardAssignedIssues($first: Int!) {
|
|
|
19287
19521
|
orderBy: updatedAt
|
|
19288
19522
|
filter: { state: { type: { nin: ["completed", "canceled"] } } }
|
|
19289
19523
|
) {
|
|
19290
|
-
nodes { ${
|
|
19524
|
+
nodes { ${LIST_ISSUE_FIELDS} }
|
|
19291
19525
|
}
|
|
19292
19526
|
}
|
|
19293
19527
|
}
|
|
@@ -19300,7 +19534,7 @@ query SideboardTeams {
|
|
|
19300
19534
|
id
|
|
19301
19535
|
key
|
|
19302
19536
|
name
|
|
19303
|
-
states { nodes { id name type } }
|
|
19537
|
+
states(first: 50) { nodes { id name type } }
|
|
19304
19538
|
}
|
|
19305
19539
|
}
|
|
19306
19540
|
}
|
|
@@ -19694,6 +19928,7 @@ async function listIssues(repoPath) {
|
|
|
19694
19928
|
}
|
|
19695
19929
|
|
|
19696
19930
|
// src/index.ts
|
|
19931
|
+
init_fetch();
|
|
19697
19932
|
init_agents();
|
|
19698
19933
|
init_spawn();
|
|
19699
19934
|
init_message_parts();
|
|
@@ -21280,25 +21515,31 @@ async function startMcpServer() {
|
|
|
21280
21515
|
}
|
|
21281
21516
|
server.tool(
|
|
21282
21517
|
"present_artifact",
|
|
21283
|
-
"Show
|
|
21518
|
+
"Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
|
|
21284
21519
|
{
|
|
21285
21520
|
title: import_zod4.z.string().describe("Short title shown in the artifact pane header"),
|
|
21286
|
-
type: import_zod4.z.enum(["html", "svg", "markdown", "react"]).describe(
|
|
21287
|
-
"
|
|
21521
|
+
type: import_zod4.z.enum(["html", "svg", "markdown", "react", "log"]).describe(
|
|
21522
|
+
"html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
|
|
21288
21523
|
),
|
|
21289
21524
|
content: import_zod4.z.string().describe(
|
|
21290
|
-
"
|
|
21525
|
+
"html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
|
|
21291
21526
|
),
|
|
21292
|
-
artifact_id: import_zod4.z.string().optional().describe("Stable id
|
|
21527
|
+
artifact_id: import_zod4.z.string().optional().describe("Stable id. Required for type=log so later calls append to the same pane."),
|
|
21528
|
+
status: import_zod4.z.enum(["running", "ok", "failed", "idle"]).optional().describe("Log header pill: running (working), ok (done), failed, idle"),
|
|
21529
|
+
phase: import_zod4.z.string().optional().describe("Log subtitle (Signing, Notarizing, \u2026)"),
|
|
21530
|
+
mode: import_zod4.z.enum(["append", "replace"]).optional().describe("log only: append (default) or replace the buffer")
|
|
21293
21531
|
},
|
|
21294
|
-
async ({ title, type, artifact_id }) => {
|
|
21532
|
+
async ({ title, type, artifact_id, status, phase, mode }) => {
|
|
21295
21533
|
const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
|
|
21296
21534
|
const payload = {
|
|
21297
21535
|
ok: true,
|
|
21298
21536
|
artifact_id: id,
|
|
21299
21537
|
title,
|
|
21300
21538
|
type,
|
|
21301
|
-
|
|
21539
|
+
status,
|
|
21540
|
+
phase,
|
|
21541
|
+
mode: type === "log" ? mode ?? "append" : void 0,
|
|
21542
|
+
message: type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
|
|
21302
21543
|
};
|
|
21303
21544
|
return { content: [{ type: "text", text: JSON.stringify(payload) }] };
|
|
21304
21545
|
}
|
|
@@ -22261,7 +22502,9 @@ init_home_board();
|
|
|
22261
22502
|
init_config();
|
|
22262
22503
|
|
|
22263
22504
|
// src/brightsy/api.ts
|
|
22505
|
+
init_fetch();
|
|
22264
22506
|
init_config();
|
|
22507
|
+
init_oauth();
|
|
22265
22508
|
var formatBrightsyFetchError = formatFetchError;
|
|
22266
22509
|
var BrightsySideboardApi = class {
|
|
22267
22510
|
cfg;
|
|
@@ -22284,7 +22527,7 @@ var BrightsySideboardApi = class {
|
|
|
22284
22527
|
return (this.cfg.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
22285
22528
|
}
|
|
22286
22529
|
async request(path2, init = {}) {
|
|
22287
|
-
await this.
|
|
22530
|
+
await this.ensureFreshAccessToken();
|
|
22288
22531
|
const url = `${this.endpoint}${path2}`;
|
|
22289
22532
|
const headers = {
|
|
22290
22533
|
Authorization: `Bearer ${this.cfg.access_token}`,
|
|
@@ -22307,33 +22550,21 @@ var BrightsySideboardApi = class {
|
|
|
22307
22550
|
}
|
|
22308
22551
|
return await res.json();
|
|
22309
22552
|
}
|
|
22310
|
-
|
|
22311
|
-
|
|
22312
|
-
if (!this.cfg.refresh_token ||
|
|
22313
|
-
|
|
22314
|
-
const url = `${this.endpoint}/oauth/token`;
|
|
22315
|
-
let res;
|
|
22316
|
-
try {
|
|
22317
|
-
res = await this.fetchImpl(url, {
|
|
22318
|
-
method: "POST",
|
|
22319
|
-
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
22320
|
-
body: new URLSearchParams({
|
|
22321
|
-
grant_type: "refresh_token",
|
|
22322
|
-
refresh_token: this.cfg.refresh_token,
|
|
22323
|
-
client_id: clientId
|
|
22324
|
-
})
|
|
22325
|
-
});
|
|
22326
|
-
} catch (err) {
|
|
22327
|
-
throw new Error(formatBrightsyFetchError(err, url));
|
|
22328
|
-
}
|
|
22329
|
-
if (!res.ok) return;
|
|
22330
|
-
const data = await res.json();
|
|
22331
|
-
if (!data.access_token) return;
|
|
22332
|
-
this.cfg.access_token = data.access_token;
|
|
22333
|
-
if (data.refresh_token) this.cfg.refresh_token = data.refresh_token;
|
|
22334
|
-
if (data.expires_in) {
|
|
22335
|
-
this.cfg.expires_at = Date.now() + data.expires_in * 1e3;
|
|
22553
|
+
/** Refresh ~/.brightsy when the access token is stale or has no expiry. */
|
|
22554
|
+
async ensureFreshAccessToken() {
|
|
22555
|
+
if (!this.cfg.refresh_token || !brightsyAccessTokenNeedsRefresh(this.cfg.expires_at)) {
|
|
22556
|
+
return;
|
|
22336
22557
|
}
|
|
22558
|
+
const grant = await refreshBrightsyAccessToken({
|
|
22559
|
+
endpoint: this.endpoint,
|
|
22560
|
+
refreshToken: this.cfg.refresh_token,
|
|
22561
|
+
clientId: this.cfg.oauth_client_id,
|
|
22562
|
+
fetchImpl: this.fetchImpl
|
|
22563
|
+
});
|
|
22564
|
+
if (!grant) return;
|
|
22565
|
+
this.cfg.access_token = grant.access_token;
|
|
22566
|
+
if (grant.refresh_token) this.cfg.refresh_token = grant.refresh_token;
|
|
22567
|
+
if (grant.expires_at) this.cfg.expires_at = grant.expires_at;
|
|
22337
22568
|
saveBrightsyConfig(this.cfg);
|
|
22338
22569
|
}
|
|
22339
22570
|
async getAccess() {
|
|
@@ -22587,6 +22818,7 @@ async function runCloudConnect(opts) {
|
|
|
22587
22818
|
// src/index.ts
|
|
22588
22819
|
init_accounts();
|
|
22589
22820
|
init_connected_teams();
|
|
22821
|
+
init_oauth();
|
|
22590
22822
|
init_injected_mcp();
|
|
22591
22823
|
|
|
22592
22824
|
// src/agents/user-mcp-config.ts
|
|
@@ -24603,6 +24835,7 @@ init_outbound_watch();
|
|
|
24603
24835
|
CONTEXT_MIN_MESSAGES,
|
|
24604
24836
|
CONVENTION_SETUP_RELPATHS,
|
|
24605
24837
|
COORDINATOR_TOOL_PLAYBOOK,
|
|
24838
|
+
DEFAULT_WORKTREE_SORT,
|
|
24606
24839
|
FAMOUS_SOCCER_TEAMS,
|
|
24607
24840
|
GITHUB_GIT_AUTH_MODES,
|
|
24608
24841
|
GLOBAL_WORKSPACE_ID,
|
|
@@ -24684,6 +24917,7 @@ init_outbound_watch();
|
|
|
24684
24917
|
autoRenameBranchEnabled,
|
|
24685
24918
|
autoRunAfterSetupEnabled,
|
|
24686
24919
|
branchDisplayLabel,
|
|
24920
|
+
brightsyAccessTokenNeedsRefresh,
|
|
24687
24921
|
brightsyAdapter,
|
|
24688
24922
|
brightsyCloudConnectAgent,
|
|
24689
24923
|
brightsyCloudConnectEnabled,
|
|
@@ -24770,7 +25004,9 @@ init_outbound_watch();
|
|
|
24770
25004
|
enrichPathWithNpmGlobalBin,
|
|
24771
25005
|
enrichWorkspacesWithGithub,
|
|
24772
25006
|
ensureAgentPath,
|
|
25007
|
+
ensureBrightsyLocalConfigFresh,
|
|
24773
25008
|
ensureCloudCoordinator,
|
|
25009
|
+
ensureConnectedBrightsyTeamTokens,
|
|
24774
25010
|
ensureGhPreferOrigin,
|
|
24775
25011
|
ensureGlobalCoordinatorCwd,
|
|
24776
25012
|
ensureReviewRequestFile,
|
|
@@ -25033,6 +25269,7 @@ init_outbound_watch();
|
|
|
25033
25269
|
readWorktreeInclude,
|
|
25034
25270
|
recordScheduleRun,
|
|
25035
25271
|
recordSlackOutboundWatch,
|
|
25272
|
+
refreshBrightsyAccessToken,
|
|
25036
25273
|
refreshGitHubAuth,
|
|
25037
25274
|
registerPackagedUserMcpClients,
|
|
25038
25275
|
releaseCaffeinateHoldForThread,
|