@sideboard-ai/core 0.1.9
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/LICENSE +190 -0
- package/dist/agents/cursor-runner.cjs +173 -0
- package/dist/agents/cursor-runner.d.cts +1 -0
- package/dist/agents/cursor-runner.d.ts +1 -0
- package/dist/agents/cursor-runner.js +102 -0
- package/dist/agents-OAX7XPKX.js +41 -0
- package/dist/app-settings-BDMLWCWI.js +61 -0
- package/dist/chunk-2M4OHXYX.js +198 -0
- package/dist/chunk-2R5VV4BA.js +143 -0
- package/dist/chunk-3DKGI32Q.js +92 -0
- package/dist/chunk-3WF3X46L.js +373 -0
- package/dist/chunk-AJ6ROGD7.js +74 -0
- package/dist/chunk-E4PWXO2C.js +4534 -0
- package/dist/chunk-HYRHI3QU.js +154 -0
- package/dist/chunk-ILQK4P5R.js +311 -0
- package/dist/chunk-LL7DTZ5B.js +1282 -0
- package/dist/chunk-M37RITA6.js +304 -0
- package/dist/chunk-TLJH3L2C.js +80 -0
- package/dist/chunk-WMCPLDW3.js +1413 -0
- package/dist/connected-teams-GF52Q7LB.js +22 -0
- package/dist/coordinator-prompt-6R2TX4WQ.js +22 -0
- package/dist/global-workspace-R44HGBU6.js +36 -0
- package/dist/index.cjs +9940 -0
- package/dist/index.d.cts +2284 -0
- package/dist/index.d.ts +2284 -0
- package/dist/index.js +929 -0
- package/dist/mcp/run-stdio.cjs +8654 -0
- package/dist/mcp/run-stdio.d.cts +2 -0
- package/dist/mcp/run-stdio.d.ts +2 -0
- package/dist/mcp/run-stdio.js +21 -0
- package/dist/paths-VPH3ITBK.js +26 -0
- package/dist/run-LF6E5IKL.js +10 -0
- package/dist/thread-store-UNPZNIFW.js +27 -0
- package/dist/title-4A2ATYNY.js +24 -0
- package/dist/workspaces-TCJFYI35.js +20 -0
- package/dist/worktree-NGFDN3J4.js +79 -0
- package/package.json +63 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import {
|
|
2
|
+
threadFilePath,
|
|
3
|
+
threadLockPath,
|
|
4
|
+
threadsDir
|
|
5
|
+
} from "./chunk-M37RITA6.js";
|
|
6
|
+
|
|
7
|
+
// src/store/thread-store.ts
|
|
8
|
+
import { randomUUID } from "crypto";
|
|
9
|
+
import {
|
|
10
|
+
existsSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
renameSync,
|
|
13
|
+
unlinkSync,
|
|
14
|
+
writeFileSync,
|
|
15
|
+
readdirSync
|
|
16
|
+
} from "fs";
|
|
17
|
+
import lockfile from "proper-lockfile";
|
|
18
|
+
function nowIso() {
|
|
19
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
20
|
+
}
|
|
21
|
+
function normalizeThread(raw) {
|
|
22
|
+
return {
|
|
23
|
+
...raw,
|
|
24
|
+
model: raw.model ?? null,
|
|
25
|
+
fast: Boolean(raw.fast),
|
|
26
|
+
planMode: Boolean(raw.planMode),
|
|
27
|
+
autonomy: raw.autonomy ?? "default",
|
|
28
|
+
lastError: raw.lastError ?? null,
|
|
29
|
+
attachments: Array.isArray(raw.attachments) ? raw.attachments : [],
|
|
30
|
+
prTitle: raw.prTitle ?? null,
|
|
31
|
+
userSetTitle: Boolean(raw.userSetTitle),
|
|
32
|
+
activeRuns: Array.isArray(raw.activeRuns) ? raw.activeRuns : []
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function createEmptyThread(partial) {
|
|
36
|
+
const ts = nowIso();
|
|
37
|
+
return {
|
|
38
|
+
id: randomUUID(),
|
|
39
|
+
sessionId: partial.sessionId ?? null,
|
|
40
|
+
autonomy: partial.autonomy ?? "default",
|
|
41
|
+
model: partial.model ?? null,
|
|
42
|
+
fast: partial.fast ?? false,
|
|
43
|
+
planMode: partial.planMode ?? false,
|
|
44
|
+
sourceIsFork: partial.sourceIsFork ?? false,
|
|
45
|
+
status: partial.status ?? "idle",
|
|
46
|
+
queue: partial.queue ?? [],
|
|
47
|
+
parentThreadId: partial.parentThreadId ?? null,
|
|
48
|
+
devPort: partial.devPort ?? null,
|
|
49
|
+
activeRuns: partial.activeRuns ?? [],
|
|
50
|
+
prUrl: partial.prUrl ?? null,
|
|
51
|
+
prTitle: partial.prTitle ?? null,
|
|
52
|
+
userSetTitle: partial.userSetTitle ?? false,
|
|
53
|
+
messages: partial.messages ?? [],
|
|
54
|
+
attachments: partial.attachments ?? [],
|
|
55
|
+
createdAt: ts,
|
|
56
|
+
updatedAt: ts,
|
|
57
|
+
title: partial.title,
|
|
58
|
+
sourceType: partial.sourceType,
|
|
59
|
+
sourceRef: partial.sourceRef,
|
|
60
|
+
branchName: partial.branchName,
|
|
61
|
+
worktreePath: partial.worktreePath,
|
|
62
|
+
repoPath: partial.repoPath,
|
|
63
|
+
agent: partial.agent,
|
|
64
|
+
lastError: null
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
async function withThreadLock(id, fn) {
|
|
68
|
+
const lockPath = threadLockPath(id);
|
|
69
|
+
writeFileSync(lockPath, "", { flag: "a" });
|
|
70
|
+
let release;
|
|
71
|
+
try {
|
|
72
|
+
release = await lockfile.lock(lockPath, {
|
|
73
|
+
retries: { retries: 10, minTimeout: 50, maxTimeout: 200 },
|
|
74
|
+
stale: 6e4
|
|
75
|
+
});
|
|
76
|
+
return await fn();
|
|
77
|
+
} finally {
|
|
78
|
+
if (release) await release();
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function readThread(id) {
|
|
82
|
+
const path = threadFilePath(id);
|
|
83
|
+
if (!existsSync(path)) return null;
|
|
84
|
+
const raw = readFileSync(path, "utf8");
|
|
85
|
+
return normalizeThread(JSON.parse(raw));
|
|
86
|
+
}
|
|
87
|
+
function writeThread(thread) {
|
|
88
|
+
const path = threadFilePath(idPath(thread.id));
|
|
89
|
+
const tmp = `${path}.${process.pid}.tmp`;
|
|
90
|
+
const next = { ...thread, updatedAt: nowIso() };
|
|
91
|
+
writeFileSync(tmp, JSON.stringify(next, null, 2), "utf8");
|
|
92
|
+
renameSync(tmp, path);
|
|
93
|
+
}
|
|
94
|
+
function idPath(id) {
|
|
95
|
+
return id;
|
|
96
|
+
}
|
|
97
|
+
function listThreads(opts) {
|
|
98
|
+
const files = readdirSync(threadsDir()).filter((f) => f.endsWith(".json"));
|
|
99
|
+
const threads = files.map((f) => {
|
|
100
|
+
try {
|
|
101
|
+
return normalizeThread(
|
|
102
|
+
JSON.parse(readFileSync(threadFilePath(f.replace(/\.json$/, "")), "utf8"))
|
|
103
|
+
);
|
|
104
|
+
} catch {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
}).filter((t) => t !== null).sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
108
|
+
if (opts?.includeArchived) return threads;
|
|
109
|
+
return threads.filter((t) => t.status !== "archived");
|
|
110
|
+
}
|
|
111
|
+
function deleteThreadRecord(id) {
|
|
112
|
+
const path = threadFilePath(id);
|
|
113
|
+
if (existsSync(path)) unlinkSync(path);
|
|
114
|
+
const lock = threadLockPath(id);
|
|
115
|
+
if (existsSync(lock)) {
|
|
116
|
+
try {
|
|
117
|
+
unlinkSync(lock);
|
|
118
|
+
} catch {
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function updateThread(id, patch) {
|
|
123
|
+
const current = readThread(id);
|
|
124
|
+
if (!current) throw new Error(`Thread not found: ${id}`);
|
|
125
|
+
const next = { ...current, ...patch, id: current.id, updatedAt: nowIso() };
|
|
126
|
+
writeThread(next);
|
|
127
|
+
return next;
|
|
128
|
+
}
|
|
129
|
+
function appendMessage(id, message) {
|
|
130
|
+
const current = readThread(id);
|
|
131
|
+
if (!current) throw new Error(`Thread not found: ${id}`);
|
|
132
|
+
return updateThread(id, { messages: [...current.messages, message] });
|
|
133
|
+
}
|
|
134
|
+
function setStatus(id, status, lastError) {
|
|
135
|
+
return updateThread(id, { status, lastError: lastError ?? null });
|
|
136
|
+
}
|
|
137
|
+
function findThreadByRef(ref) {
|
|
138
|
+
const all = listThreads({ includeArchived: true });
|
|
139
|
+
return all.find((t) => t.id === ref || t.id.startsWith(ref) || t.branchName === ref || t.title === ref) ?? null;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export {
|
|
143
|
+
normalizeThread,
|
|
144
|
+
createEmptyThread,
|
|
145
|
+
withThreadLock,
|
|
146
|
+
readThread,
|
|
147
|
+
writeThread,
|
|
148
|
+
listThreads,
|
|
149
|
+
deleteThreadRecord,
|
|
150
|
+
updateThread,
|
|
151
|
+
appendMessage,
|
|
152
|
+
setStatus,
|
|
153
|
+
findThreadByRef
|
|
154
|
+
};
|
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appDataDir
|
|
3
|
+
} from "./chunk-M37RITA6.js";
|
|
4
|
+
import {
|
|
5
|
+
run
|
|
6
|
+
} from "./chunk-AJ6ROGD7.js";
|
|
7
|
+
|
|
8
|
+
// src/brightsy/connected-teams.ts
|
|
9
|
+
import { existsSync as existsSync2, mkdirSync, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
10
|
+
import { join as join2 } from "path";
|
|
11
|
+
|
|
12
|
+
// src/brightsy/config.ts
|
|
13
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
14
|
+
import { homedir } from "os";
|
|
15
|
+
import { join } from "path";
|
|
16
|
+
function brightsyConfigPath() {
|
|
17
|
+
return join(homedir(), ".brightsy", "config.json");
|
|
18
|
+
}
|
|
19
|
+
function loadBrightsyConfig() {
|
|
20
|
+
const path = brightsyConfigPath();
|
|
21
|
+
if (!existsSync(path)) {
|
|
22
|
+
throw new Error("Brightsy not logged in \u2014 run `brightsy login` first");
|
|
23
|
+
}
|
|
24
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
25
|
+
if (!raw.access_token || !raw.account_id) {
|
|
26
|
+
throw new Error("Brightsy config incomplete \u2014 run `brightsy login`");
|
|
27
|
+
}
|
|
28
|
+
return raw;
|
|
29
|
+
}
|
|
30
|
+
function saveBrightsyConfig(cfg) {
|
|
31
|
+
writeFileSync(brightsyConfigPath(), `${JSON.stringify(cfg, null, 2)}
|
|
32
|
+
`, {
|
|
33
|
+
mode: 384
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// src/brightsy/accounts.ts
|
|
38
|
+
async function loadConnectedTeams() {
|
|
39
|
+
const { listConnectedBrightsyTeams: listConnectedBrightsyTeams2 } = await import("./connected-teams-GF52Q7LB.js");
|
|
40
|
+
return listConnectedBrightsyTeams2();
|
|
41
|
+
}
|
|
42
|
+
async function runBrightsyTeamsJson(args) {
|
|
43
|
+
const listed = await run("brightsy", ["teams", ...args, "--json"], {
|
|
44
|
+
reject: false
|
|
45
|
+
});
|
|
46
|
+
if (listed.exitCode !== 0) {
|
|
47
|
+
throw new Error(
|
|
48
|
+
listed.stderr.trim() || listed.stdout.trim() || "brightsy teams failed \u2014 is `@brightsy/cli` installed and logged in?"
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
const raw = listed.stdout.trim();
|
|
52
|
+
if (!raw) {
|
|
53
|
+
throw new Error("brightsy teams returned empty output");
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
return JSON.parse(raw);
|
|
57
|
+
} catch {
|
|
58
|
+
throw new Error("brightsy teams returned invalid JSON");
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
async function listBrightsyAccounts() {
|
|
62
|
+
const data = await runBrightsyTeamsJson([]);
|
|
63
|
+
return Array.isArray(data.teams) ? data.teams : [];
|
|
64
|
+
}
|
|
65
|
+
async function getBrightsySession() {
|
|
66
|
+
try {
|
|
67
|
+
loadBrightsyConfig();
|
|
68
|
+
const data = await runBrightsyTeamsJson([]);
|
|
69
|
+
const accounts = Array.isArray(data.teams) ? data.teams : [];
|
|
70
|
+
const active = data.active ?? accounts.find((a) => a.active) ?? null;
|
|
71
|
+
const { ensureCliTeamTracked: ensureCliTeamTracked2 } = await import("./connected-teams-GF52Q7LB.js");
|
|
72
|
+
const connectedTeams = ensureCliTeamTracked2(
|
|
73
|
+
active ? { id: active.id, slug: active.slug, name: active.name } : void 0
|
|
74
|
+
);
|
|
75
|
+
return {
|
|
76
|
+
connected: true,
|
|
77
|
+
endpoint: (data.endpoint || "https://brightsy.ai").replace(/\/$/, ""),
|
|
78
|
+
accountId: active?.id ?? null,
|
|
79
|
+
accountSlug: active?.slug ?? null,
|
|
80
|
+
accounts,
|
|
81
|
+
connectedTeams
|
|
82
|
+
};
|
|
83
|
+
} catch (err) {
|
|
84
|
+
return {
|
|
85
|
+
connected: false,
|
|
86
|
+
endpoint: "https://brightsy.ai",
|
|
87
|
+
accountId: null,
|
|
88
|
+
accountSlug: null,
|
|
89
|
+
accounts: [],
|
|
90
|
+
connectedTeams: await loadConnectedTeams(),
|
|
91
|
+
reason: err instanceof Error ? err.message : String(err)
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
async function performBrightsyAccountSwitch(accountIdOrSlug) {
|
|
96
|
+
const data = await runBrightsyTeamsJson([
|
|
97
|
+
"switch",
|
|
98
|
+
accountIdOrSlug
|
|
99
|
+
]);
|
|
100
|
+
if (!data.active?.id) {
|
|
101
|
+
throw new Error(`Team switch failed for: ${accountIdOrSlug}`);
|
|
102
|
+
}
|
|
103
|
+
const cfg = loadBrightsyConfig();
|
|
104
|
+
if (data.active.slug && data.active.slug !== cfg.account_slug) {
|
|
105
|
+
cfg.account_slug = data.active.slug;
|
|
106
|
+
saveBrightsyConfig(cfg);
|
|
107
|
+
}
|
|
108
|
+
return { cfg, target: data.active };
|
|
109
|
+
}
|
|
110
|
+
async function switchBrightsyAccount(accountIdOrSlug) {
|
|
111
|
+
const { connectBrightsyTeam: connectBrightsyTeam2 } = await import("./connected-teams-GF52Q7LB.js");
|
|
112
|
+
await connectBrightsyTeam2(accountIdOrSlug);
|
|
113
|
+
return getBrightsySession();
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/brightsy/connected-teams.ts
|
|
117
|
+
function storePath() {
|
|
118
|
+
return join2(appDataDir(), "brightsy-teams.json");
|
|
119
|
+
}
|
|
120
|
+
function readStore() {
|
|
121
|
+
const path = storePath();
|
|
122
|
+
if (!existsSync2(path)) return [];
|
|
123
|
+
try {
|
|
124
|
+
const parsed = JSON.parse(readFileSync2(path, "utf8"));
|
|
125
|
+
return Array.isArray(parsed.teams) ? parsed.teams : [];
|
|
126
|
+
} catch {
|
|
127
|
+
return [];
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
function writeStore(teams) {
|
|
131
|
+
mkdirSync(appDataDir(), { recursive: true });
|
|
132
|
+
const path = storePath();
|
|
133
|
+
writeFileSync2(path, `${JSON.stringify({ teams }, null, 2)}
|
|
134
|
+
`, {
|
|
135
|
+
mode: 384
|
|
136
|
+
});
|
|
137
|
+
return teams;
|
|
138
|
+
}
|
|
139
|
+
function listConnectedBrightsyTeams() {
|
|
140
|
+
return readStore().map(({ id, slug, name, expires_at }) => ({
|
|
141
|
+
id,
|
|
142
|
+
slug,
|
|
143
|
+
name,
|
|
144
|
+
expires_at
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
function getConnectedBrightsyTeamsRaw() {
|
|
148
|
+
return readStore();
|
|
149
|
+
}
|
|
150
|
+
function applyConnectedTeamToCli(team) {
|
|
151
|
+
let base = {};
|
|
152
|
+
try {
|
|
153
|
+
base = loadBrightsyConfig();
|
|
154
|
+
} catch {
|
|
155
|
+
}
|
|
156
|
+
saveBrightsyConfig({
|
|
157
|
+
...base,
|
|
158
|
+
access_token: team.access_token,
|
|
159
|
+
refresh_token: team.refresh_token ?? base.refresh_token,
|
|
160
|
+
expires_at: team.expires_at ?? base.expires_at,
|
|
161
|
+
account_id: team.id,
|
|
162
|
+
account_slug: team.slug,
|
|
163
|
+
endpoint: team.endpoint ?? base.endpoint ?? "https://brightsy.ai",
|
|
164
|
+
oauth_client_id: base.oauth_client_id
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
async function refreshTeamToken(team) {
|
|
168
|
+
if (!team.refresh_token) return team;
|
|
169
|
+
const endpoint = (team.endpoint || "https://brightsy.ai").replace(/\/$/, "");
|
|
170
|
+
const cfg = (() => {
|
|
171
|
+
try {
|
|
172
|
+
return loadBrightsyConfig();
|
|
173
|
+
} catch {
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
})();
|
|
177
|
+
const clientId = cfg?.oauth_client_id || "brightsy-cli";
|
|
178
|
+
const res = await fetch(`${endpoint}/oauth/token`, {
|
|
179
|
+
method: "POST",
|
|
180
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
181
|
+
body: new URLSearchParams({
|
|
182
|
+
grant_type: "refresh_token",
|
|
183
|
+
refresh_token: team.refresh_token,
|
|
184
|
+
client_id: clientId
|
|
185
|
+
})
|
|
186
|
+
});
|
|
187
|
+
if (!res.ok) return team;
|
|
188
|
+
const data = await res.json();
|
|
189
|
+
if (!data.access_token) return team;
|
|
190
|
+
return {
|
|
191
|
+
...team,
|
|
192
|
+
access_token: data.access_token,
|
|
193
|
+
refresh_token: data.refresh_token || team.refresh_token,
|
|
194
|
+
expires_at: data.expires_in ? Date.now() + data.expires_in * 1e3 : team.expires_at
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
async function ensureConnectedBrightsyTeamTokens() {
|
|
198
|
+
const teams = readStore();
|
|
199
|
+
if (teams.length === 0) return [];
|
|
200
|
+
const next = [];
|
|
201
|
+
let changed = false;
|
|
202
|
+
for (const team of teams) {
|
|
203
|
+
const expired = typeof team.expires_at === "number" && Date.now() >= team.expires_at - 6e4;
|
|
204
|
+
if (!expired) {
|
|
205
|
+
next.push(team);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
const refreshed = await refreshTeamToken(team);
|
|
209
|
+
if (refreshed.access_token !== team.access_token) changed = true;
|
|
210
|
+
next.push(refreshed);
|
|
211
|
+
}
|
|
212
|
+
if (changed) writeStore(next);
|
|
213
|
+
try {
|
|
214
|
+
const cfg = loadBrightsyConfig();
|
|
215
|
+
const active = next.find((t) => t.id === cfg.account_id);
|
|
216
|
+
if (active && active.access_token !== cfg.access_token) {
|
|
217
|
+
applyConnectedTeamToCli(active);
|
|
218
|
+
}
|
|
219
|
+
} catch {
|
|
220
|
+
}
|
|
221
|
+
return next;
|
|
222
|
+
}
|
|
223
|
+
function ensureCliTeamTracked(meta) {
|
|
224
|
+
try {
|
|
225
|
+
const cfg = loadBrightsyConfig();
|
|
226
|
+
const existing = readStore();
|
|
227
|
+
if (existing.some((t) => t.id === cfg.account_id)) {
|
|
228
|
+
return listConnectedBrightsyTeams();
|
|
229
|
+
}
|
|
230
|
+
const team = {
|
|
231
|
+
id: cfg.account_id,
|
|
232
|
+
slug: meta?.slug || cfg.account_slug || cfg.account_id,
|
|
233
|
+
name: meta?.name || cfg.account_slug || cfg.account_id,
|
|
234
|
+
access_token: cfg.access_token,
|
|
235
|
+
refresh_token: cfg.refresh_token,
|
|
236
|
+
expires_at: cfg.expires_at,
|
|
237
|
+
endpoint: cfg.endpoint
|
|
238
|
+
};
|
|
239
|
+
writeStore([...existing, team]);
|
|
240
|
+
} catch {
|
|
241
|
+
}
|
|
242
|
+
return listConnectedBrightsyTeams();
|
|
243
|
+
}
|
|
244
|
+
async function connectBrightsyTeam(accountIdOrSlug) {
|
|
245
|
+
const accounts = await listBrightsyAccounts();
|
|
246
|
+
const target = accounts.find((a) => a.id === accountIdOrSlug) ?? accounts.find((a) => a.slug === accountIdOrSlug);
|
|
247
|
+
if (!target) {
|
|
248
|
+
throw new Error(`Brightsy team not found: ${accountIdOrSlug}`);
|
|
249
|
+
}
|
|
250
|
+
const existing = readStore();
|
|
251
|
+
const already = existing.find((t) => t.id === target.id);
|
|
252
|
+
if (already) {
|
|
253
|
+
applyConnectedTeamToCli(already);
|
|
254
|
+
return listConnectedBrightsyTeams();
|
|
255
|
+
}
|
|
256
|
+
const { cfg: minted } = await performBrightsyAccountSwitch(target.id);
|
|
257
|
+
const team = {
|
|
258
|
+
id: target.id,
|
|
259
|
+
slug: target.slug,
|
|
260
|
+
name: target.name,
|
|
261
|
+
access_token: minted.access_token,
|
|
262
|
+
refresh_token: minted.refresh_token,
|
|
263
|
+
expires_at: minted.expires_at,
|
|
264
|
+
endpoint: minted.endpoint
|
|
265
|
+
};
|
|
266
|
+
writeStore([...existing, team]);
|
|
267
|
+
return listConnectedBrightsyTeams();
|
|
268
|
+
}
|
|
269
|
+
async function disconnectBrightsyTeam(accountIdOrSlug) {
|
|
270
|
+
const before = readStore();
|
|
271
|
+
const removed = before.find(
|
|
272
|
+
(t) => t.id === accountIdOrSlug || t.slug === accountIdOrSlug
|
|
273
|
+
);
|
|
274
|
+
const teams = before.filter(
|
|
275
|
+
(t) => t.id !== accountIdOrSlug && t.slug !== accountIdOrSlug
|
|
276
|
+
);
|
|
277
|
+
writeStore(teams);
|
|
278
|
+
if (removed) {
|
|
279
|
+
try {
|
|
280
|
+
const cfg = loadBrightsyConfig();
|
|
281
|
+
if (cfg.account_id === removed.id) {
|
|
282
|
+
if (teams[0]) {
|
|
283
|
+
applyConnectedTeamToCli(teams[0]);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
} catch {
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return listConnectedBrightsyTeams();
|
|
290
|
+
}
|
|
291
|
+
function brightsyMcpServerName(slug) {
|
|
292
|
+
const cleaned = slug.replace(/[^A-Za-z0-9_-]/g, "_").replace(/^_+|_+$/g, "");
|
|
293
|
+
return `brightsy_${cleaned || "team"}`;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
export {
|
|
297
|
+
brightsyConfigPath,
|
|
298
|
+
loadBrightsyConfig,
|
|
299
|
+
saveBrightsyConfig,
|
|
300
|
+
listBrightsyAccounts,
|
|
301
|
+
getBrightsySession,
|
|
302
|
+
switchBrightsyAccount,
|
|
303
|
+
listConnectedBrightsyTeams,
|
|
304
|
+
getConnectedBrightsyTeamsRaw,
|
|
305
|
+
applyConnectedTeamToCli,
|
|
306
|
+
ensureConnectedBrightsyTeamTokens,
|
|
307
|
+
ensureCliTeamTracked,
|
|
308
|
+
connectBrightsyTeam,
|
|
309
|
+
disconnectBrightsyTeam,
|
|
310
|
+
brightsyMcpServerName
|
|
311
|
+
};
|