@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
|
@@ -28,8 +28,9 @@ import {
|
|
|
28
28
|
resolveCursorModelId,
|
|
29
29
|
resolveLoginCommand,
|
|
30
30
|
resolveQuotaFallbackAgent
|
|
31
|
-
} from "./chunk-
|
|
32
|
-
import "./chunk-
|
|
31
|
+
} from "./chunk-MGYCQAZ6.js";
|
|
32
|
+
import "./chunk-SIPDL62B.js";
|
|
33
|
+
import "./chunk-AQESMTCZ.js";
|
|
33
34
|
import {
|
|
34
35
|
ORCHESTRATOR_AGENT_KINDS,
|
|
35
36
|
assertOrchestratorCapableAgent,
|
|
@@ -42,7 +43,7 @@ import {
|
|
|
42
43
|
parseCursorRunnerLine,
|
|
43
44
|
preferredCursorCostCents,
|
|
44
45
|
turnCostUsdFromCursorUsage
|
|
45
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-FSCQXMGI.js";
|
|
46
47
|
import "./chunk-UDQI3N47.js";
|
|
47
48
|
import "./chunk-FKOIHGKV.js";
|
|
48
49
|
import "./chunk-HUYEU4GS.js";
|
|
@@ -34,8 +34,9 @@ import {
|
|
|
34
34
|
resolveLoginCommand,
|
|
35
35
|
resolveQuotaFallbackAgent,
|
|
36
36
|
turnCostUsdFromCursorUsage
|
|
37
|
-
} from "./chunk-
|
|
38
|
-
import "./chunk-
|
|
37
|
+
} from "./chunk-PK4PQUPU.js";
|
|
38
|
+
import "./chunk-LLX3OMHU.js";
|
|
39
|
+
import "./chunk-R7FGPBKL.js";
|
|
39
40
|
import {
|
|
40
41
|
ORCHESTRATOR_AGENT_KINDS,
|
|
41
42
|
assertOrchestratorCapableAgent,
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
// src/http/fetch.ts
|
|
2
|
+
var injected = null;
|
|
3
|
+
function setHttpFetchImpl(fetchImpl) {
|
|
4
|
+
injected = fetchImpl;
|
|
5
|
+
}
|
|
6
|
+
function formatFetchError(err, url) {
|
|
7
|
+
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
8
|
+
const cause = err.cause;
|
|
9
|
+
let detail = "";
|
|
10
|
+
if (cause instanceof Error) {
|
|
11
|
+
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
12
|
+
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
13
|
+
} else if (cause != null) {
|
|
14
|
+
detail = ` [${String(cause)}]`;
|
|
15
|
+
}
|
|
16
|
+
return `${err.message}${detail} (${url})`;
|
|
17
|
+
}
|
|
18
|
+
async function httpFetch(input, init) {
|
|
19
|
+
const url = typeof input === "string" ? input : input.href;
|
|
20
|
+
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
21
|
+
try {
|
|
22
|
+
return await fn(url, init);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
throw new Error(formatFetchError(err, url));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/brightsy/config.ts
|
|
29
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
30
|
+
import { homedir } from "os";
|
|
31
|
+
import { join } from "path";
|
|
32
|
+
function brightsyConfigPath() {
|
|
33
|
+
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
34
|
+
if (override) return override;
|
|
35
|
+
return join(homedir(), ".brightsy", "config.json");
|
|
36
|
+
}
|
|
37
|
+
function loadBrightsyConfig() {
|
|
38
|
+
const path = brightsyConfigPath();
|
|
39
|
+
if (!existsSync(path)) {
|
|
40
|
+
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
41
|
+
}
|
|
42
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
43
|
+
if (!raw.access_token || !raw.account_id) {
|
|
44
|
+
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
}
|
|
48
|
+
function saveBrightsyConfig(cfg) {
|
|
49
|
+
writeFileSync(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
50
|
+
`, {
|
|
51
|
+
mode: 384
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/brightsy/oauth.ts
|
|
56
|
+
var REFRESH_SKEW_MS = 6e4;
|
|
57
|
+
function brightsyAccessTokenNeedsRefresh(expiresAt, now = Date.now()) {
|
|
58
|
+
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt) || expiresAt <= 0) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return now >= expiresAt - REFRESH_SKEW_MS;
|
|
62
|
+
}
|
|
63
|
+
function applyGrant(current, grant) {
|
|
64
|
+
return {
|
|
65
|
+
access_token: grant.access_token,
|
|
66
|
+
refresh_token: grant.refresh_token || current.refresh_token,
|
|
67
|
+
expires_at: grant.expires_at ?? current.expires_at
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function refreshBrightsyAccessToken(opts) {
|
|
71
|
+
const endpoint = (opts.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
72
|
+
const url = `${endpoint}/oauth/token`;
|
|
73
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
74
|
+
let res;
|
|
75
|
+
try {
|
|
76
|
+
res = await fetchImpl(url, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
79
|
+
body: new URLSearchParams({
|
|
80
|
+
grant_type: "refresh_token",
|
|
81
|
+
refresh_token: opts.refreshToken,
|
|
82
|
+
client_id: opts.clientId || "brightsy-cli"
|
|
83
|
+
})
|
|
84
|
+
});
|
|
85
|
+
} catch (err) {
|
|
86
|
+
throw new Error(formatFetchError(err, url));
|
|
87
|
+
}
|
|
88
|
+
if (!res.ok) return null;
|
|
89
|
+
const data = await res.json();
|
|
90
|
+
if (!data.access_token) return null;
|
|
91
|
+
return {
|
|
92
|
+
access_token: data.access_token,
|
|
93
|
+
refresh_token: data.refresh_token,
|
|
94
|
+
expires_at: data.expires_in ? Date.now() + data.expires_in * 1e3 : void 0
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async function ensureBrightsyLocalConfigFresh(opts) {
|
|
98
|
+
let cfg;
|
|
99
|
+
try {
|
|
100
|
+
cfg = loadBrightsyConfig();
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (!cfg.refresh_token || !brightsyAccessTokenNeedsRefresh(cfg.expires_at)) {
|
|
105
|
+
return cfg;
|
|
106
|
+
}
|
|
107
|
+
const grant = await refreshBrightsyAccessToken({
|
|
108
|
+
endpoint: cfg.endpoint || "https://brightsy.ai",
|
|
109
|
+
refreshToken: cfg.refresh_token,
|
|
110
|
+
clientId: cfg.oauth_client_id,
|
|
111
|
+
fetchImpl: opts?.fetchImpl
|
|
112
|
+
});
|
|
113
|
+
if (!grant) return cfg;
|
|
114
|
+
const next = { ...cfg, ...applyGrant(cfg, grant) };
|
|
115
|
+
saveBrightsyConfig(next);
|
|
116
|
+
return next;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export {
|
|
120
|
+
brightsyConfigPath,
|
|
121
|
+
loadBrightsyConfig,
|
|
122
|
+
saveBrightsyConfig,
|
|
123
|
+
setHttpFetchImpl,
|
|
124
|
+
formatFetchError,
|
|
125
|
+
httpFetch,
|
|
126
|
+
brightsyAccessTokenNeedsRefresh,
|
|
127
|
+
refreshBrightsyAccessToken,
|
|
128
|
+
ensureBrightsyLocalConfigFresh
|
|
129
|
+
};
|
|
@@ -211,11 +211,40 @@ function humanizeAgentFailDetail(detail) {
|
|
|
211
211
|
}
|
|
212
212
|
function turnFailChatText(opts) {
|
|
213
213
|
const chat = opts.assistantText.trim();
|
|
214
|
-
if (
|
|
215
|
-
if (opts.exitCode === 0) return "";
|
|
214
|
+
if (opts.exitCode === 0) return chat;
|
|
216
215
|
const detail = opts.detail.trim();
|
|
217
|
-
|
|
218
|
-
|
|
216
|
+
const fail = detail ? humanizeAgentFailDetail(detail) : formatTurnExitError(opts.exitCode ?? 1, "");
|
|
217
|
+
if (!chat) return fail;
|
|
218
|
+
const failCore = fail.replace(/^exit\s*\d+:\s*/i, "").trim();
|
|
219
|
+
if (looksLikeAgentFailureMessage(chat) || failCore && chat.includes(failCore) || chat.includes(fail)) {
|
|
220
|
+
return chat;
|
|
221
|
+
}
|
|
222
|
+
return `${chat}
|
|
223
|
+
|
|
224
|
+
${fail}`;
|
|
225
|
+
}
|
|
226
|
+
function shouldFeedErrorBackToAgent(opts) {
|
|
227
|
+
const detail = opts.detail.trim();
|
|
228
|
+
const chat = (opts.assistantText ?? "").trim();
|
|
229
|
+
if (looksLikeAgentFailureMessage(detail) || looksLikeAgentFailureMessage(chat)) {
|
|
230
|
+
return false;
|
|
231
|
+
}
|
|
232
|
+
if (looksLikeInvalidAgentSession(detail) || looksLikeV8Oom(detail) || looksLikeRetryableRunnerCrash(detail)) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
if (/without details|segfault|sig(?:segv|abrt|ill)|fatal error/i.test(detail)) {
|
|
236
|
+
return true;
|
|
237
|
+
}
|
|
238
|
+
return !chat && (opts.partsCount ?? 0) === 0;
|
|
239
|
+
}
|
|
240
|
+
function formatAgentErrorContinuePrompt(detail) {
|
|
241
|
+
const fail = humanizeAgentFailDetail(detail.trim()) || "the agent process exited without details";
|
|
242
|
+
return [
|
|
243
|
+
"The previous agent process ended before it finished. Error:",
|
|
244
|
+
fail,
|
|
245
|
+
"",
|
|
246
|
+
"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."
|
|
247
|
+
].join("\n");
|
|
219
248
|
}
|
|
220
249
|
function formatTurnExitError(exitCode, stderrSummary) {
|
|
221
250
|
const code = exitCode ?? 1;
|
|
@@ -860,6 +889,8 @@ export {
|
|
|
860
889
|
looksLikeAgentFailureMessage,
|
|
861
890
|
fallbackTurnFailDetail,
|
|
862
891
|
turnFailChatText,
|
|
892
|
+
shouldFeedErrorBackToAgent,
|
|
893
|
+
formatAgentErrorContinuePrompt,
|
|
863
894
|
formatTurnExitError,
|
|
864
895
|
packagedCursorRunnerPath,
|
|
865
896
|
packagedMcpStdioPath,
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import {
|
|
4
|
+
brightsyAccessTokenNeedsRefresh,
|
|
5
|
+
ensureBrightsyLocalConfigFresh,
|
|
6
|
+
loadBrightsyConfig,
|
|
7
|
+
refreshBrightsyAccessToken,
|
|
8
|
+
saveBrightsyConfig
|
|
9
|
+
} from "./chunk-R7FGPBKL.js";
|
|
3
10
|
import {
|
|
4
11
|
run
|
|
5
12
|
} from "./chunk-KPIYENTF.js";
|
|
@@ -8,33 +15,8 @@ import {
|
|
|
8
15
|
} from "./chunk-BD2ICC4D.js";
|
|
9
16
|
|
|
10
17
|
// src/brightsy/connected-teams.ts
|
|
11
|
-
import { existsSync
|
|
12
|
-
import { join as join2 } from "path";
|
|
13
|
-
|
|
14
|
-
// src/brightsy/config.ts
|
|
15
|
-
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
16
|
-
import { homedir } from "os";
|
|
18
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
17
19
|
import { join } from "path";
|
|
18
|
-
function brightsyConfigPath() {
|
|
19
|
-
return join(homedir(), ".brightsy", "config.json");
|
|
20
|
-
}
|
|
21
|
-
function loadBrightsyConfig() {
|
|
22
|
-
const path = brightsyConfigPath();
|
|
23
|
-
if (!existsSync(path)) {
|
|
24
|
-
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
25
|
-
}
|
|
26
|
-
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
27
|
-
if (!raw.access_token || !raw.account_id) {
|
|
28
|
-
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
29
|
-
}
|
|
30
|
-
return raw;
|
|
31
|
-
}
|
|
32
|
-
function saveBrightsyConfig(cfg) {
|
|
33
|
-
writeFileSync(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
34
|
-
`, {
|
|
35
|
-
mode: 384
|
|
36
|
-
});
|
|
37
|
-
}
|
|
38
20
|
|
|
39
21
|
// src/brightsy/accounts.ts
|
|
40
22
|
async function runBrightsyTeamsJson(args) {
|
|
@@ -78,13 +60,13 @@ async function performBrightsyAccountSwitch(accountIdOrSlug) {
|
|
|
78
60
|
|
|
79
61
|
// src/brightsy/connected-teams.ts
|
|
80
62
|
function storePath() {
|
|
81
|
-
return
|
|
63
|
+
return join(appDataDir(), "brightsy-teams.json");
|
|
82
64
|
}
|
|
83
65
|
function readStore() {
|
|
84
66
|
const path = storePath();
|
|
85
|
-
if (!
|
|
67
|
+
if (!existsSync(path)) return [];
|
|
86
68
|
try {
|
|
87
|
-
const parsed = JSON.parse(
|
|
69
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
88
70
|
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
89
71
|
} catch {
|
|
90
72
|
return [];
|
|
@@ -93,7 +75,7 @@ function readStore() {
|
|
|
93
75
|
function writeStore(teams) {
|
|
94
76
|
mkdirSync(appDataDir(), { recursive: true });
|
|
95
77
|
const path = storePath();
|
|
96
|
-
|
|
78
|
+
writeFileSync(path, `${JSON.stringify({ teams }, null, 2)}
|
|
97
79
|
`, {
|
|
98
80
|
mode: 384
|
|
99
81
|
});
|
|
@@ -129,7 +111,6 @@ function applyConnectedTeamToCli(team) {
|
|
|
129
111
|
}
|
|
130
112
|
async function refreshTeamToken(team) {
|
|
131
113
|
if (!team.refresh_token) return team;
|
|
132
|
-
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
133
114
|
const cfg = (() => {
|
|
134
115
|
try {
|
|
135
116
|
return loadBrightsyConfig();
|
|
@@ -137,39 +118,34 @@ async function refreshTeamToken(team) {
|
|
|
137
118
|
return null;
|
|
138
119
|
}
|
|
139
120
|
})();
|
|
140
|
-
const
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
body: new URLSearchParams({
|
|
145
|
-
grant_type: "refresh_token",
|
|
146
|
-
refresh_token: team.refresh_token,
|
|
147
|
-
client_id: clientId
|
|
148
|
-
})
|
|
121
|
+
const grant = await refreshBrightsyAccessToken({
|
|
122
|
+
endpoint: team.endpoint || "https://brightsy.ai",
|
|
123
|
+
refreshToken: team.refresh_token,
|
|
124
|
+
clientId: cfg?.oauth_client_id
|
|
149
125
|
});
|
|
150
|
-
if (!
|
|
151
|
-
const data = await res.json();
|
|
152
|
-
if (!data.access_token) return team;
|
|
126
|
+
if (!grant) return team;
|
|
153
127
|
return {
|
|
154
128
|
...team,
|
|
155
|
-
access_token:
|
|
156
|
-
refresh_token:
|
|
157
|
-
expires_at:
|
|
129
|
+
access_token: grant.access_token,
|
|
130
|
+
refresh_token: grant.refresh_token || team.refresh_token,
|
|
131
|
+
expires_at: grant.expires_at ?? team.expires_at
|
|
158
132
|
};
|
|
159
133
|
}
|
|
160
134
|
async function ensureConnectedBrightsyTeamTokens() {
|
|
135
|
+
await ensureBrightsyLocalConfigFresh().catch(() => null);
|
|
161
136
|
const teams = readStore();
|
|
162
137
|
if (teams.length === 0) return [];
|
|
163
138
|
const next = [];
|
|
164
139
|
let changed = false;
|
|
165
140
|
for (const team of teams) {
|
|
166
|
-
|
|
167
|
-
if (!expired) {
|
|
141
|
+
if (!team.refresh_token || !brightsyAccessTokenNeedsRefresh(team.expires_at)) {
|
|
168
142
|
next.push(team);
|
|
169
143
|
continue;
|
|
170
144
|
}
|
|
171
145
|
const refreshed = await refreshTeamToken(team);
|
|
172
|
-
if (refreshed.access_token !== team.access_token
|
|
146
|
+
if (refreshed.access_token !== team.access_token || refreshed.refresh_token !== team.refresh_token || refreshed.expires_at !== team.expires_at) {
|
|
147
|
+
changed = true;
|
|
148
|
+
}
|
|
173
149
|
next.push(refreshed);
|
|
174
150
|
}
|
|
175
151
|
if (changed) writeStore(next);
|
|
@@ -257,7 +233,6 @@ function brightsyMcpServerName(slug) {
|
|
|
257
233
|
}
|
|
258
234
|
|
|
259
235
|
export {
|
|
260
|
-
loadBrightsyConfig,
|
|
261
236
|
listConnectedBrightsyTeams,
|
|
262
237
|
getConnectedBrightsyTeamsRaw,
|
|
263
238
|
applyConnectedTeamToCli,
|
|
@@ -2,9 +2,11 @@ import {
|
|
|
2
2
|
applyConnectedTeamToCli,
|
|
3
3
|
brightsyMcpServerName,
|
|
4
4
|
ensureCliTeamTracked,
|
|
5
|
-
ensureConnectedBrightsyTeamTokens
|
|
5
|
+
ensureConnectedBrightsyTeamTokens
|
|
6
|
+
} from "./chunk-SIPDL62B.js";
|
|
7
|
+
import {
|
|
6
8
|
loadBrightsyConfig
|
|
7
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-AQESMTCZ.js";
|
|
8
10
|
import {
|
|
9
11
|
isOrchestratorThread
|
|
10
12
|
} from "./chunk-HULESWLI.js";
|
|
@@ -20,7 +22,7 @@ import {
|
|
|
20
22
|
packagedMcpStdioPath,
|
|
21
23
|
parseCursorRunnerLine,
|
|
22
24
|
resolveNodeLaunch
|
|
23
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-FSCQXMGI.js";
|
|
24
26
|
import {
|
|
25
27
|
codexUnattendedGitConfigArgs,
|
|
26
28
|
mergeAgentGitAuthEnv,
|
|
@@ -1174,6 +1176,7 @@ function teamEnv(team) {
|
|
|
1174
1176
|
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
1175
1177
|
return {
|
|
1176
1178
|
BRIGHTSY_API_TOKEN: team.access_token,
|
|
1179
|
+
...team.refresh_token ? { BRIGHTSY_REFRESH_TOKEN: team.refresh_token } : {},
|
|
1177
1180
|
BRIGHTSY_ACCOUNT_ID: team.id,
|
|
1178
1181
|
BRIGHTSY_API_URL: endpoint
|
|
1179
1182
|
};
|
|
@@ -1439,11 +1442,17 @@ var CLAUDE_CHROME_ALLOWED_TOOLS = [
|
|
|
1439
1442
|
"Skill(claude-in-chrome)"
|
|
1440
1443
|
];
|
|
1441
1444
|
var CLAUDE_PROMPT_ARG_MAX = 2e5;
|
|
1445
|
+
var mcpListCache = null;
|
|
1442
1446
|
async function loadMcpServers() {
|
|
1447
|
+
if (mcpListCache && Date.now() - mcpListCache.at < 3e4) {
|
|
1448
|
+
return mcpListCache.servers;
|
|
1449
|
+
}
|
|
1443
1450
|
const claude = resolveClaudeExecutable();
|
|
1444
1451
|
const mcpText = await run(claude, ["mcp", "list"], { reject: false });
|
|
1445
|
-
|
|
1452
|
+
const servers = parseMcpList(`${mcpText.stdout}
|
|
1446
1453
|
${mcpText.stderr}`);
|
|
1454
|
+
mcpListCache = { at: Date.now(), servers };
|
|
1455
|
+
return servers;
|
|
1447
1456
|
}
|
|
1448
1457
|
function usageFromClaude(usage) {
|
|
1449
1458
|
if (!usage) return null;
|
|
@@ -2704,10 +2713,13 @@ var opencodeAdapter = {
|
|
|
2704
2713
|
const part = obj.part;
|
|
2705
2714
|
const id = part?.tool_use_id ?? part?.id ?? obj.tool_use_id ?? obj.id;
|
|
2706
2715
|
if (!id) return null;
|
|
2716
|
+
const flagged = obj.isError === true || obj.is_error === true;
|
|
2717
|
+
const errText = formatUnknownDetail(obj.error);
|
|
2707
2718
|
return {
|
|
2708
2719
|
type: "tool_result",
|
|
2709
2720
|
id,
|
|
2710
|
-
content: part?.output ?? part?.content ?? obj.output ?? obj.content
|
|
2721
|
+
content: part?.output ?? part?.content ?? obj.output ?? obj.content ?? (errText || void 0),
|
|
2722
|
+
isError: flagged || Boolean(errText)
|
|
2711
2723
|
};
|
|
2712
2724
|
}
|
|
2713
2725
|
if (obj.type === "step_finish" || obj.type === "step-finish") {
|
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
applyConnectedTeamToCli,
|
|
5
5
|
brightsyMcpServerName,
|
|
6
6
|
ensureCliTeamTracked,
|
|
7
|
-
ensureConnectedBrightsyTeamTokens
|
|
7
|
+
ensureConnectedBrightsyTeamTokens
|
|
8
|
+
} from "./chunk-LLX3OMHU.js";
|
|
9
|
+
import {
|
|
8
10
|
loadBrightsyConfig
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-R7FGPBKL.js";
|
|
10
12
|
import {
|
|
11
13
|
isOrchestratorThread
|
|
12
14
|
} from "./chunk-MNL4FSKY.js";
|
|
@@ -353,11 +355,40 @@ function humanizeAgentFailDetail(detail) {
|
|
|
353
355
|
}
|
|
354
356
|
function turnFailChatText(opts) {
|
|
355
357
|
const chat = opts.assistantText.trim();
|
|
356
|
-
if (
|
|
357
|
-
if (opts.exitCode === 0) return "";
|
|
358
|
+
if (opts.exitCode === 0) return chat;
|
|
358
359
|
const detail = opts.detail.trim();
|
|
359
|
-
|
|
360
|
-
|
|
360
|
+
const fail = detail ? humanizeAgentFailDetail(detail) : formatTurnExitError(opts.exitCode ?? 1, "");
|
|
361
|
+
if (!chat) return fail;
|
|
362
|
+
const failCore = fail.replace(/^exit\s*\d+:\s*/i, "").trim();
|
|
363
|
+
if (looksLikeAgentFailureMessage(chat) || failCore && chat.includes(failCore) || chat.includes(fail)) {
|
|
364
|
+
return chat;
|
|
365
|
+
}
|
|
366
|
+
return `${chat}
|
|
367
|
+
|
|
368
|
+
${fail}`;
|
|
369
|
+
}
|
|
370
|
+
function shouldFeedErrorBackToAgent(opts) {
|
|
371
|
+
const detail = opts.detail.trim();
|
|
372
|
+
const chat = (opts.assistantText ?? "").trim();
|
|
373
|
+
if (looksLikeAgentFailureMessage(detail) || looksLikeAgentFailureMessage(chat)) {
|
|
374
|
+
return false;
|
|
375
|
+
}
|
|
376
|
+
if (looksLikeInvalidAgentSession(detail) || looksLikeV8Oom(detail) || looksLikeRetryableRunnerCrash(detail)) {
|
|
377
|
+
return true;
|
|
378
|
+
}
|
|
379
|
+
if (/without details|segfault|sig(?:segv|abrt|ill)|fatal error/i.test(detail)) {
|
|
380
|
+
return true;
|
|
381
|
+
}
|
|
382
|
+
return !chat && (opts.partsCount ?? 0) === 0;
|
|
383
|
+
}
|
|
384
|
+
function formatAgentErrorContinuePrompt(detail) {
|
|
385
|
+
const fail = humanizeAgentFailDetail(detail.trim()) || "the agent process exited without details";
|
|
386
|
+
return [
|
|
387
|
+
"The previous agent process ended before it finished. Error:",
|
|
388
|
+
fail,
|
|
389
|
+
"",
|
|
390
|
+
"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."
|
|
391
|
+
].join("\n");
|
|
361
392
|
}
|
|
362
393
|
function formatTurnExitError(exitCode, stderrSummary) {
|
|
363
394
|
const code = exitCode ?? 1;
|
|
@@ -1495,6 +1526,7 @@ function teamEnv(team) {
|
|
|
1495
1526
|
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
1496
1527
|
return {
|
|
1497
1528
|
BRIGHTSY_API_TOKEN: team.access_token,
|
|
1529
|
+
...team.refresh_token ? { BRIGHTSY_REFRESH_TOKEN: team.refresh_token } : {},
|
|
1498
1530
|
BRIGHTSY_ACCOUNT_ID: team.id,
|
|
1499
1531
|
BRIGHTSY_API_URL: endpoint
|
|
1500
1532
|
};
|
|
@@ -1757,11 +1789,17 @@ var CLAUDE_CHROME_ALLOWED_TOOLS = [
|
|
|
1757
1789
|
"Skill(claude-in-chrome)"
|
|
1758
1790
|
];
|
|
1759
1791
|
var CLAUDE_PROMPT_ARG_MAX = 2e5;
|
|
1792
|
+
var mcpListCache = null;
|
|
1760
1793
|
async function loadMcpServers() {
|
|
1794
|
+
if (mcpListCache && Date.now() - mcpListCache.at < 3e4) {
|
|
1795
|
+
return mcpListCache.servers;
|
|
1796
|
+
}
|
|
1761
1797
|
const claude = resolveClaudeExecutable();
|
|
1762
1798
|
const mcpText = await run(claude, ["mcp", "list"], { reject: false });
|
|
1763
|
-
|
|
1799
|
+
const servers = parseMcpList(`${mcpText.stdout}
|
|
1764
1800
|
${mcpText.stderr}`);
|
|
1801
|
+
mcpListCache = { at: Date.now(), servers };
|
|
1802
|
+
return servers;
|
|
1765
1803
|
}
|
|
1766
1804
|
function usageFromClaude(usage) {
|
|
1767
1805
|
if (!usage) return null;
|
|
@@ -3295,10 +3333,13 @@ var opencodeAdapter = {
|
|
|
3295
3333
|
const part = obj.part;
|
|
3296
3334
|
const id = part?.tool_use_id ?? part?.id ?? obj.tool_use_id ?? obj.id;
|
|
3297
3335
|
if (!id) return null;
|
|
3336
|
+
const flagged = obj.isError === true || obj.is_error === true;
|
|
3337
|
+
const errText = formatUnknownDetail(obj.error);
|
|
3298
3338
|
return {
|
|
3299
3339
|
type: "tool_result",
|
|
3300
3340
|
id,
|
|
3301
|
-
content: part?.output ?? part?.content ?? obj.output ?? obj.content
|
|
3341
|
+
content: part?.output ?? part?.content ?? obj.output ?? obj.content ?? (errText || void 0),
|
|
3342
|
+
isError: flagged || Boolean(errText)
|
|
3302
3343
|
};
|
|
3303
3344
|
}
|
|
3304
3345
|
if (obj.type === "step_finish" || obj.type === "step-finish") {
|
|
@@ -3822,6 +3863,8 @@ export {
|
|
|
3822
3863
|
looksLikeAgentFailureMessage,
|
|
3823
3864
|
fallbackTurnFailDetail,
|
|
3824
3865
|
turnFailChatText,
|
|
3866
|
+
shouldFeedErrorBackToAgent,
|
|
3867
|
+
formatAgentErrorContinuePrompt,
|
|
3825
3868
|
formatTurnExitError,
|
|
3826
3869
|
sumUsageList,
|
|
3827
3870
|
applyTurnUsage,
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
// src/http/fetch.ts
|
|
5
|
+
var injected = null;
|
|
6
|
+
function formatFetchError(err, url) {
|
|
7
|
+
if (!(err instanceof Error)) return `${String(err)} (${url})`;
|
|
8
|
+
const cause = err.cause;
|
|
9
|
+
let detail = "";
|
|
10
|
+
if (cause instanceof Error) {
|
|
11
|
+
const code = typeof cause.code === "string" ? cause.code : void 0;
|
|
12
|
+
detail = code ? ` [${code}: ${cause.message}]` : ` [${cause.message}]`;
|
|
13
|
+
} else if (cause != null) {
|
|
14
|
+
detail = ` [${String(cause)}]`;
|
|
15
|
+
}
|
|
16
|
+
return `${err.message}${detail} (${url})`;
|
|
17
|
+
}
|
|
18
|
+
async function httpFetch(input, init) {
|
|
19
|
+
const url = typeof input === "string" ? input : input.href;
|
|
20
|
+
const fn = injected ?? globalThis.fetch.bind(globalThis);
|
|
21
|
+
try {
|
|
22
|
+
return await fn(url, init);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
throw new Error(formatFetchError(err, url));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/brightsy/config.ts
|
|
29
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
30
|
+
import { homedir } from "os";
|
|
31
|
+
import { join } from "path";
|
|
32
|
+
function brightsyConfigPath() {
|
|
33
|
+
const override = process.env.BRIGHTSY_CONFIG?.trim();
|
|
34
|
+
if (override) return override;
|
|
35
|
+
return join(homedir(), ".brightsy", "config.json");
|
|
36
|
+
}
|
|
37
|
+
function loadBrightsyConfig() {
|
|
38
|
+
const path = brightsyConfigPath();
|
|
39
|
+
if (!existsSync(path)) {
|
|
40
|
+
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
41
|
+
}
|
|
42
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
43
|
+
if (!raw.access_token || !raw.account_id) {
|
|
44
|
+
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
45
|
+
}
|
|
46
|
+
return raw;
|
|
47
|
+
}
|
|
48
|
+
function saveBrightsyConfig(cfg) {
|
|
49
|
+
writeFileSync(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
50
|
+
`, {
|
|
51
|
+
mode: 384
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/brightsy/oauth.ts
|
|
56
|
+
var REFRESH_SKEW_MS = 6e4;
|
|
57
|
+
function brightsyAccessTokenNeedsRefresh(expiresAt, now = Date.now()) {
|
|
58
|
+
if (typeof expiresAt !== "number" || !Number.isFinite(expiresAt) || expiresAt <= 0) {
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
return now >= expiresAt - REFRESH_SKEW_MS;
|
|
62
|
+
}
|
|
63
|
+
function applyGrant(current, grant) {
|
|
64
|
+
return {
|
|
65
|
+
access_token: grant.access_token,
|
|
66
|
+
refresh_token: grant.refresh_token || current.refresh_token,
|
|
67
|
+
expires_at: grant.expires_at ?? current.expires_at
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
async function refreshBrightsyAccessToken(opts) {
|
|
71
|
+
const endpoint = (opts.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
72
|
+
const url = `${endpoint}/oauth/token`;
|
|
73
|
+
const fetchImpl = opts.fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
74
|
+
let res;
|
|
75
|
+
try {
|
|
76
|
+
res = await fetchImpl(url, {
|
|
77
|
+
method: "POST",
|
|
78
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
79
|
+
body: new URLSearchParams({
|
|
80
|
+
grant_type: "refresh_token",
|
|
81
|
+
refresh_token: opts.refreshToken,
|
|
82
|
+
client_id: opts.clientId || "brightsy-cli"
|
|
83
|
+
})
|
|
84
|
+
});
|
|
85
|
+
} catch (err) {
|
|
86
|
+
throw new Error(formatFetchError(err, url));
|
|
87
|
+
}
|
|
88
|
+
if (!res.ok) return null;
|
|
89
|
+
const data = await res.json();
|
|
90
|
+
if (!data.access_token) return null;
|
|
91
|
+
return {
|
|
92
|
+
access_token: data.access_token,
|
|
93
|
+
refresh_token: data.refresh_token,
|
|
94
|
+
expires_at: data.expires_in ? Date.now() + data.expires_in * 1e3 : void 0
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
async function ensureBrightsyLocalConfigFresh(opts) {
|
|
98
|
+
let cfg;
|
|
99
|
+
try {
|
|
100
|
+
cfg = loadBrightsyConfig();
|
|
101
|
+
} catch {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
if (!cfg.refresh_token || !brightsyAccessTokenNeedsRefresh(cfg.expires_at)) {
|
|
105
|
+
return cfg;
|
|
106
|
+
}
|
|
107
|
+
const grant = await refreshBrightsyAccessToken({
|
|
108
|
+
endpoint: cfg.endpoint || "https://brightsy.ai",
|
|
109
|
+
refreshToken: cfg.refresh_token,
|
|
110
|
+
clientId: cfg.oauth_client_id,
|
|
111
|
+
fetchImpl: opts?.fetchImpl
|
|
112
|
+
});
|
|
113
|
+
if (!grant) return cfg;
|
|
114
|
+
const next = { ...cfg, ...applyGrant(cfg, grant) };
|
|
115
|
+
saveBrightsyConfig(next);
|
|
116
|
+
return next;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export {
|
|
120
|
+
loadBrightsyConfig,
|
|
121
|
+
saveBrightsyConfig,
|
|
122
|
+
httpFetch,
|
|
123
|
+
brightsyAccessTokenNeedsRefresh,
|
|
124
|
+
refreshBrightsyAccessToken,
|
|
125
|
+
ensureBrightsyLocalConfigFresh
|
|
126
|
+
};
|