@sideboard-ai/core 0.1.152 → 0.1.155
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/{abletime-223A3LY6.js → abletime-H7LPGIP2.js} +3 -3
- package/dist/{abletime-CLC5UJC2.js → abletime-JSTJLXAW.js} +3 -3
- package/dist/agents/cursor-runner.js +2 -2
- package/dist/{agents-CUKWIM34.js → agents-V24DYZI4.js} +8 -9
- package/dist/{agents-VHXCBBBD.js → agents-YVW75KBO.js} +8 -9
- package/dist/{app-settings-3CHCNIMD.js → app-settings-H3INSR67.js} +38 -4
- package/dist/{app-settings-J3JBCUOT.js → app-settings-VRQI3FIE.js} +38 -4
- package/dist/{caffeinate-hold-NBRUWYXO.js → caffeinate-hold-DBKMRZZO.js} +2 -2
- package/dist/{caffeinate-hold-X3JNPR42.js → caffeinate-hold-SK2QISPE.js} +2 -2
- package/dist/chunk-2F63IMCL.js +959 -0
- package/dist/{chunk-4XNSGDXE.js → chunk-3BWVOUQG.js} +244 -1
- package/dist/{chunk-7BQNSUR2.js → chunk-46ZTBUVJ.js} +364 -200
- package/dist/{chunk-EY6QXPPO.js → chunk-4THE3EY7.js} +6 -6
- package/dist/{chunk-TUGKX5BD.js → chunk-7UURXPKD.js} +1 -1
- package/dist/{chunk-DCOZABNT.js → chunk-AO35MGOE.js} +1 -1
- package/dist/{chunk-3JBMACYX.js → chunk-CJQLPPEJ.js} +387 -15
- package/dist/{chunk-CZD4NRDZ.js → chunk-D7EGJ3EI.js} +244 -1
- package/dist/{chunk-QZQEXME2.js → chunk-EFVFB2AH.js} +1 -1
- package/dist/{chunk-B7XK37WZ.js → chunk-FDCFXMDG.js} +1 -1
- package/dist/{chunk-6X7Z34XE.js → chunk-J2OKVOBM.js} +410 -188
- package/dist/{chunk-WLV7TRMR.js → chunk-JOK4XWBG.js} +1 -1
- package/dist/{chunk-BD2ICC4D.js → chunk-JTJHOYCU.js} +1 -1
- package/dist/{chunk-GE7M3QTE.js → chunk-LQMFCS54.js} +387 -15
- package/dist/{chunk-G7SIQFBQ.js → chunk-LZ6QMEQC.js} +1 -1
- package/dist/{chunk-EUXOHTUK.js → chunk-LZQULFIT.js} +1 -1
- package/dist/{chunk-KLBOWJ74.js → chunk-OCQPTUR7.js} +1 -1
- package/dist/{chunk-GFQ57XAX.js → chunk-QZEZXYVV.js} +13 -13
- package/dist/chunk-RNC3GR6L.js +905 -0
- package/dist/{chunk-VHX673DI.js → chunk-WLPXZFRE.js} +1 -1
- package/dist/{chunk-7F4XE6UG.js → chunk-XD2BAANL.js} +5 -5
- package/dist/{connected-teams-XO766HB4.js → connected-teams-DBWAMP7G.js} +2 -2
- package/dist/{connected-teams-I2WZZZFA.js → connected-teams-WGONUQOF.js} +2 -2
- package/dist/{coordinator-prompt-WGFRYCHE.js → coordinator-prompt-7FHKCWXB.js} +5 -5
- package/dist/{coordinator-prompt-TBX4MOFM.js → coordinator-prompt-KX2FVVYT.js} +5 -5
- package/dist/{cursor-recover-NOQYOFRF.js → cursor-recover-L5MD6MBO.js} +1 -1
- package/dist/{cursor-recover-QSLWEZNA.js → cursor-recover-NDMLLNYX.js} +2 -2
- package/dist/{global-workspace-IY5QAV5C.js → global-workspace-2BRRKSDN.js} +5 -6
- package/dist/{global-workspace-BHLUJ46D.js → global-workspace-4LHCZ2DC.js} +5 -6
- package/dist/index.cjs +1889 -777
- package/dist/index.d.cts +222 -12
- package/dist/index.d.ts +222 -12
- package/dist/index.js +304 -108
- package/dist/mcp/run-stdio.cjs +1747 -1240
- package/dist/mcp/run-stdio.js +232 -80
- package/dist/{orchestrator-256DFPSX.js → orchestrator-3FWEKDAQ.js} +9 -11
- package/dist/{orchestrator-NUA6SEV7.js → orchestrator-HC7XVGJB.js} +10 -12
- package/dist/{paths-UMEDHOS5.js → paths-53TLA7VQ.js} +1 -1
- package/dist/{paths-QCI3MTO5.js → paths-RRCLNSJB.js} +1 -1
- package/dist/{thread-store-WGASXXXR.js → thread-store-KBFBHT5G.js} +2 -2
- package/dist/{thread-store-57ZLHR3A.js → thread-store-MVQU6HPJ.js} +2 -2
- package/dist/{workspaces-4FSXVIZM.js → workspaces-5UNDTN4G.js} +5 -7
- package/dist/{workspaces-NECIQTAO.js → workspaces-MQYNZXUK.js} +5 -7
- package/dist/{worktree-HTUM35NT.js → worktree-PEWDAX5O.js} +4 -4
- package/dist/{worktree-DPIREDFR.js → worktree-T4SWFSTT.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-2U6QF3PT.js +0 -211
- package/dist/chunk-67TIJ7S5.js +0 -122
- package/dist/chunk-7TIUOYBK.js +0 -213
- package/dist/chunk-G4MTYUWS.js +0 -592
- package/dist/chunk-K2ANSHUO.js +0 -120
- package/dist/chunk-SN6CMKF6.js +0 -538
package/dist/chunk-G4MTYUWS.js
DELETED
|
@@ -1,592 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ensureGlobalCoordinatorCwd
|
|
3
|
-
} from "./chunk-2U6QF3PT.js";
|
|
4
|
-
import {
|
|
5
|
-
allocateTeamName,
|
|
6
|
-
takenSlugsFromThread,
|
|
7
|
-
teamSlugFromName
|
|
8
|
-
} from "./chunk-GE7M3QTE.js";
|
|
9
|
-
import {
|
|
10
|
-
ATTACHMENTS_DIR,
|
|
11
|
-
attachmentsGitignoreBody
|
|
12
|
-
} from "./chunk-JRH62XC4.js";
|
|
13
|
-
import {
|
|
14
|
-
resolveNewThreadOptions,
|
|
15
|
-
resolveThreadDefaults
|
|
16
|
-
} from "./chunk-4XNSGDXE.js";
|
|
17
|
-
import {
|
|
18
|
-
createEmptyThread,
|
|
19
|
-
listThreads,
|
|
20
|
-
updateThread,
|
|
21
|
-
writeThread
|
|
22
|
-
} from "./chunk-TUGKX5BD.js";
|
|
23
|
-
import {
|
|
24
|
-
globalAgentCwd
|
|
25
|
-
} from "./chunk-QZQEXME2.js";
|
|
26
|
-
|
|
27
|
-
// src/brightsy/cloud-connect-constants.ts
|
|
28
|
-
var CLOUD_ORCHESTRATOR_GOAL = "Cloud-connected Sideboard orchestrator";
|
|
29
|
-
var SIDEBOARD_FORCE_STOP = "SIDEBOARD_FORCE_STOP";
|
|
30
|
-
var CLOUD_COORDINATOR_BUSY_REPLY = [
|
|
31
|
-
"Sideboard is busy with an in-progress client/desktop tool turn on the global coordinator.",
|
|
32
|
-
"I did not start a new orchestration turn.",
|
|
33
|
-
`To force-stop the in-progress turn, send another desktop request whose first line is exactly ${SIDEBOARD_FORCE_STOP}`,
|
|
34
|
-
"(optional follow-up request on later lines).",
|
|
35
|
-
"What do you want me to do? (retry later, wait until idle, force-stop, rephrase, or cancel)"
|
|
36
|
-
].join(" ");
|
|
37
|
-
var CLOUD_COORDINATOR_STOPPED_REPLY = [
|
|
38
|
-
"Sideboard force-stopped the in-progress global coordinator turn.",
|
|
39
|
-
"No new orchestration request was started."
|
|
40
|
-
].join(" ");
|
|
41
|
-
var CLOUD_COORDINATOR_TIMEOUT_REPLY = [
|
|
42
|
-
"Sideboard global coordinator timed out waiting for the local agent turn to finish.",
|
|
43
|
-
"I did not produce a full orchestration result.",
|
|
44
|
-
`To force-stop the in-progress turn, send another desktop request whose first line is exactly ${SIDEBOARD_FORCE_STOP}`,
|
|
45
|
-
"(optional follow-up request on later lines).",
|
|
46
|
-
"What do you want me to do? (retry later, wait, force-stop, rephrase, or cancel)"
|
|
47
|
-
].join(" ");
|
|
48
|
-
function parseForceStopMessage(message) {
|
|
49
|
-
const normalized = message.replace(/\r\n/g, "\n");
|
|
50
|
-
const nl = normalized.indexOf("\n");
|
|
51
|
-
const firstLine = (nl === -1 ? normalized : normalized.slice(0, nl)).trim();
|
|
52
|
-
const remainder = (nl === -1 ? "" : normalized.slice(nl + 1)).trim();
|
|
53
|
-
const forceStop = firstLine.toLowerCase() === SIDEBOARD_FORCE_STOP.toLowerCase();
|
|
54
|
-
return { forceStop, remainder: forceStop ? remainder : message };
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
// src/composer/stage-files.ts
|
|
58
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
|
|
59
|
-
import { basename, extname, join } from "path";
|
|
60
|
-
import { randomUUID } from "crypto";
|
|
61
|
-
var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
62
|
-
"png",
|
|
63
|
-
"jpg",
|
|
64
|
-
"jpeg",
|
|
65
|
-
"gif",
|
|
66
|
-
"webp",
|
|
67
|
-
"svg",
|
|
68
|
-
"bmp",
|
|
69
|
-
"ico"
|
|
70
|
-
]);
|
|
71
|
-
var IMAGE_MIME_BY_EXT = {
|
|
72
|
-
png: "image/png",
|
|
73
|
-
jpg: "image/jpeg",
|
|
74
|
-
jpeg: "image/jpeg",
|
|
75
|
-
gif: "image/gif",
|
|
76
|
-
webp: "image/webp",
|
|
77
|
-
svg: "image/svg+xml",
|
|
78
|
-
bmp: "image/bmp",
|
|
79
|
-
ico: "image/x-icon"
|
|
80
|
-
};
|
|
81
|
-
var MAX_INLINE_BYTES = 4e5;
|
|
82
|
-
var MAX_PREVIEW_BYTES = 5e6;
|
|
83
|
-
function fileExtension(filePath) {
|
|
84
|
-
const base = basename(filePath).toLowerCase();
|
|
85
|
-
return base.includes(".") ? base.split(".").pop() || "" : "";
|
|
86
|
-
}
|
|
87
|
-
function isImageFilePath(filePath) {
|
|
88
|
-
return IMAGE_EXTENSIONS.has(fileExtension(filePath));
|
|
89
|
-
}
|
|
90
|
-
function imageMimeType(filePath) {
|
|
91
|
-
return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
|
|
92
|
-
}
|
|
93
|
-
function ensureAttachmentsDir(worktreePath) {
|
|
94
|
-
const dir = join(worktreePath, ATTACHMENTS_DIR);
|
|
95
|
-
mkdirSync(dir, { recursive: true });
|
|
96
|
-
const gi = join(dir, ".gitignore");
|
|
97
|
-
if (!existsSync(gi)) {
|
|
98
|
-
writeFileSync(gi, attachmentsGitignoreBody(), "utf8");
|
|
99
|
-
}
|
|
100
|
-
return dir;
|
|
101
|
-
}
|
|
102
|
-
function uniqueAttachmentName(dir, originalName) {
|
|
103
|
-
const safe = originalName.replace(/[/\\]/g, "_") || "file";
|
|
104
|
-
if (!existsSync(join(dir, safe))) return safe;
|
|
105
|
-
const ext = extname(safe);
|
|
106
|
-
const stem = ext ? safe.slice(0, -ext.length) : safe;
|
|
107
|
-
for (let i = 1; i < 1e4; i++) {
|
|
108
|
-
const candidate = `${stem}-${i}${ext}`;
|
|
109
|
-
if (!existsSync(join(dir, candidate))) return candidate;
|
|
110
|
-
}
|
|
111
|
-
return `${stem}-${randomUUID()}${ext}`;
|
|
112
|
-
}
|
|
113
|
-
function previewDataUrlFromBuf(filePath, buf) {
|
|
114
|
-
if (!isImageFilePath(filePath)) return void 0;
|
|
115
|
-
if (buf.length > MAX_PREVIEW_BYTES) return void 0;
|
|
116
|
-
return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
|
|
117
|
-
}
|
|
118
|
-
function attachmentFromBuffer(name, buf, opts) {
|
|
119
|
-
const previewDataUrl = previewDataUrlFromBuf(name, buf);
|
|
120
|
-
if (isImageFilePath(name)) {
|
|
121
|
-
const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
|
|
122
|
-
return {
|
|
123
|
-
id: randomUUID(),
|
|
124
|
-
name,
|
|
125
|
-
kind: "file",
|
|
126
|
-
path: opts.path,
|
|
127
|
-
previewDataUrl,
|
|
128
|
-
content: [
|
|
129
|
-
`Image attached: ${pathHint}`,
|
|
130
|
-
opts.path ? `Use the Read tool on \`${opts.path}\` to view this image.` : "The image is shown in the composer; copy it into the worktree if you need to inspect pixels."
|
|
131
|
-
].join("\n")
|
|
132
|
-
};
|
|
133
|
-
}
|
|
134
|
-
if (buf.length > MAX_INLINE_BYTES) {
|
|
135
|
-
return {
|
|
136
|
-
id: randomUUID(),
|
|
137
|
-
name,
|
|
138
|
-
kind: "file",
|
|
139
|
-
path: opts.path,
|
|
140
|
-
content: opts.path ? `(file too large to attach inline: \`${opts.path}\`, ${buf.length} bytes \u2014 use the Read tool)` : `(file too large to attach inline: ${opts.sourceLabel || name}, ${buf.length} bytes)`
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
if (buf.includes(0)) {
|
|
144
|
-
return {
|
|
145
|
-
id: randomUUID(),
|
|
146
|
-
name,
|
|
147
|
-
kind: "file",
|
|
148
|
-
path: opts.path,
|
|
149
|
-
content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
|
-
return {
|
|
153
|
-
id: randomUUID(),
|
|
154
|
-
name,
|
|
155
|
-
kind: "file",
|
|
156
|
-
path: opts.path,
|
|
157
|
-
content: buf.toString("utf8")
|
|
158
|
-
};
|
|
159
|
-
}
|
|
160
|
-
function attachmentFromAbsolutePath(absolutePath) {
|
|
161
|
-
const name = basename(absolutePath);
|
|
162
|
-
try {
|
|
163
|
-
const st = statSync(absolutePath);
|
|
164
|
-
if (!st.isFile()) {
|
|
165
|
-
return {
|
|
166
|
-
id: randomUUID(),
|
|
167
|
-
name,
|
|
168
|
-
kind: "file",
|
|
169
|
-
content: `(not a file: ${absolutePath})`
|
|
170
|
-
};
|
|
171
|
-
}
|
|
172
|
-
const buf = readFileSync(absolutePath);
|
|
173
|
-
return attachmentFromBuffer(name, buf, { sourceLabel: absolutePath });
|
|
174
|
-
} catch (err) {
|
|
175
|
-
return {
|
|
176
|
-
id: randomUUID(),
|
|
177
|
-
name,
|
|
178
|
-
kind: "file",
|
|
179
|
-
content: `(could not read ${absolutePath}: ${err instanceof Error ? err.message : String(err)})`
|
|
180
|
-
};
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
|
|
184
|
-
if (absolutePaths.length === 0) return [];
|
|
185
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
186
|
-
const out = [];
|
|
187
|
-
for (const abs of absolutePaths) {
|
|
188
|
-
const originalName = basename(abs);
|
|
189
|
-
try {
|
|
190
|
-
const st = statSync(abs);
|
|
191
|
-
if (!st.isFile()) continue;
|
|
192
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
193
|
-
const destAbs = join(dir, name);
|
|
194
|
-
copyFileSync(abs, destAbs);
|
|
195
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
196
|
-
const buf = readFileSync(destAbs);
|
|
197
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
198
|
-
} catch (err) {
|
|
199
|
-
out.push({
|
|
200
|
-
id: randomUUID(),
|
|
201
|
-
name: originalName,
|
|
202
|
-
kind: "file",
|
|
203
|
-
content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
|
|
204
|
-
});
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
return out;
|
|
208
|
-
}
|
|
209
|
-
function stageBuffersAsAttachments(worktreePath, buffers) {
|
|
210
|
-
if (buffers.length === 0) return [];
|
|
211
|
-
const dir = ensureAttachmentsDir(worktreePath);
|
|
212
|
-
const out = [];
|
|
213
|
-
for (const item of buffers) {
|
|
214
|
-
const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
215
|
-
try {
|
|
216
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
217
|
-
const name = uniqueAttachmentName(dir, originalName);
|
|
218
|
-
const destAbs = join(dir, name);
|
|
219
|
-
writeFileSync(destAbs, buf);
|
|
220
|
-
const rel = `${ATTACHMENTS_DIR}/${name}`;
|
|
221
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel }));
|
|
222
|
-
} catch (err) {
|
|
223
|
-
out.push({
|
|
224
|
-
id: randomUUID(),
|
|
225
|
-
name: originalName,
|
|
226
|
-
kind: "file",
|
|
227
|
-
content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
|
|
228
|
-
});
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
return out;
|
|
232
|
-
}
|
|
233
|
-
function attachmentsFromBuffers(buffers) {
|
|
234
|
-
return buffers.map((item) => {
|
|
235
|
-
const name = (item.name || "file").replace(/[/\\]/g, "_") || "file";
|
|
236
|
-
try {
|
|
237
|
-
const buf = Buffer.from(item.dataBase64, "base64");
|
|
238
|
-
return attachmentFromBuffer(name, buf, { sourceLabel: name });
|
|
239
|
-
} catch (err) {
|
|
240
|
-
return {
|
|
241
|
-
id: randomUUID(),
|
|
242
|
-
name,
|
|
243
|
-
kind: "file",
|
|
244
|
-
content: `(could not attach ${name}: ${err instanceof Error ? err.message : String(err)})`
|
|
245
|
-
};
|
|
246
|
-
}
|
|
247
|
-
});
|
|
248
|
-
}
|
|
249
|
-
function isWorktreeRelativePath(p) {
|
|
250
|
-
if (!p || p.includes("..")) return false;
|
|
251
|
-
if (p.startsWith("/")) return false;
|
|
252
|
-
if (/^[A-Za-z]:[\\/]/.test(p)) return false;
|
|
253
|
-
return true;
|
|
254
|
-
}
|
|
255
|
-
function dataUrlToBase64(url) {
|
|
256
|
-
if (!url) return null;
|
|
257
|
-
const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
|
|
258
|
-
return m?.[1] ?? null;
|
|
259
|
-
}
|
|
260
|
-
var IMAGE_HINT_RE = /^Image attached:/;
|
|
261
|
-
var PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
|
|
262
|
-
function persistPendingFileAttachments(worktreePath, attachments) {
|
|
263
|
-
if (attachments.length === 0) return attachments;
|
|
264
|
-
const keep = [];
|
|
265
|
-
const buffers = [];
|
|
266
|
-
for (const att of attachments) {
|
|
267
|
-
if (att.kind !== "file") {
|
|
268
|
-
keep.push(att);
|
|
269
|
-
continue;
|
|
270
|
-
}
|
|
271
|
-
if (att.path && isWorktreeRelativePath(att.path)) {
|
|
272
|
-
keep.push(att);
|
|
273
|
-
continue;
|
|
274
|
-
}
|
|
275
|
-
const fromPreview = dataUrlToBase64(att.previewDataUrl);
|
|
276
|
-
if (fromPreview) {
|
|
277
|
-
buffers.push({ name: att.name, dataBase64: fromPreview });
|
|
278
|
-
continue;
|
|
279
|
-
}
|
|
280
|
-
if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
|
|
281
|
-
buffers.push({
|
|
282
|
-
name: att.name,
|
|
283
|
-
dataBase64: Buffer.from(att.content, "utf8").toString("base64")
|
|
284
|
-
});
|
|
285
|
-
continue;
|
|
286
|
-
}
|
|
287
|
-
keep.push(att);
|
|
288
|
-
}
|
|
289
|
-
if (buffers.length === 0) return attachments;
|
|
290
|
-
return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers)];
|
|
291
|
-
}
|
|
292
|
-
function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
|
|
293
|
-
const out = [];
|
|
294
|
-
for (const rel of relativePaths) {
|
|
295
|
-
if (!rel || rel.includes("..") || rel.startsWith("/")) {
|
|
296
|
-
out.push({
|
|
297
|
-
id: randomUUID(),
|
|
298
|
-
name: basename(rel) || "file",
|
|
299
|
-
kind: "file",
|
|
300
|
-
content: `(invalid path: ${rel})`
|
|
301
|
-
});
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
const name = basename(rel);
|
|
305
|
-
try {
|
|
306
|
-
const abs = join(worktreePath, rel);
|
|
307
|
-
const st = statSync(abs);
|
|
308
|
-
if (!st.isFile()) continue;
|
|
309
|
-
const buf = readFileSync(abs);
|
|
310
|
-
out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
|
|
311
|
-
} catch (err) {
|
|
312
|
-
out.push({
|
|
313
|
-
id: randomUUID(),
|
|
314
|
-
name,
|
|
315
|
-
kind: "file",
|
|
316
|
-
content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
|
|
317
|
-
});
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
return out;
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// src/agents/orchestrator-capable.ts
|
|
324
|
-
var ORCHESTRATOR_AGENT_KINDS = [
|
|
325
|
-
"claude",
|
|
326
|
-
"codex",
|
|
327
|
-
"opencode",
|
|
328
|
-
"cursor"
|
|
329
|
-
];
|
|
330
|
-
function isOrchestratorCapableAgent(agent) {
|
|
331
|
-
return Boolean(
|
|
332
|
-
agent && ORCHESTRATOR_AGENT_KINDS.includes(agent)
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
function assertOrchestratorCapableAgent(agent, context = "orchestration") {
|
|
336
|
-
if (!isOrchestratorCapableAgent(agent)) {
|
|
337
|
-
throw new Error(
|
|
338
|
-
`${agent} cannot run ${context} \u2014 it does not support Sideboard MCP. Use Claude, Cursor, Codex, or OpenCode.`
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
return agent;
|
|
342
|
-
}
|
|
343
|
-
function coerceOrchestratorAgent(agent, fallback = "claude") {
|
|
344
|
-
return isOrchestratorCapableAgent(agent) ? agent : fallback;
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// src/store/global-workspace.ts
|
|
348
|
-
var GLOBAL_WORKSPACE_ID = "__global__";
|
|
349
|
-
function isGlobalThread(thread) {
|
|
350
|
-
return Boolean(thread && thread.repoPath === GLOBAL_WORKSPACE_ID);
|
|
351
|
-
}
|
|
352
|
-
function isGlobalRepoPath(repoPath) {
|
|
353
|
-
return repoPath === GLOBAL_WORKSPACE_ID;
|
|
354
|
-
}
|
|
355
|
-
function isOrchestratorThread(thread) {
|
|
356
|
-
return Boolean(
|
|
357
|
-
thread && (thread.sourceType === "orchestration" || isGlobalThread(thread))
|
|
358
|
-
);
|
|
359
|
-
}
|
|
360
|
-
function orchestratorSessionPoisonedByBuiltins(thread) {
|
|
361
|
-
if (!thread?.messages?.length) return false;
|
|
362
|
-
let usedBuiltin = false;
|
|
363
|
-
let usedSideboardMcp = false;
|
|
364
|
-
for (const msg of thread.messages) {
|
|
365
|
-
for (const part of msg.parts ?? []) {
|
|
366
|
-
if (part.type !== "tool") continue;
|
|
367
|
-
if (part.name.startsWith("mcp__sideboard")) {
|
|
368
|
-
usedSideboardMcp = true;
|
|
369
|
-
} else if (part.name === "Bash" || part.name === "Edit" || part.name === "Write" || part.name === "Read" || part.name === "Glob" || part.name === "Grep") {
|
|
370
|
-
usedBuiltin = true;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
}
|
|
374
|
-
return usedBuiltin && !usedSideboardMcp;
|
|
375
|
-
}
|
|
376
|
-
function isCloudCoordinatorThread(thread) {
|
|
377
|
-
if (thread.sourceRef === CLOUD_ORCHESTRATOR_GOAL) {
|
|
378
|
-
return isGlobalThread(thread) || thread.sourceType === "orchestration";
|
|
379
|
-
}
|
|
380
|
-
if (thread.title === CLOUD_ORCHESTRATOR_GOAL) {
|
|
381
|
-
return isGlobalThread(thread) || thread.sourceType === "orchestration";
|
|
382
|
-
}
|
|
383
|
-
return false;
|
|
384
|
-
}
|
|
385
|
-
function orchestrationTitleNeedsSoccerNickname(thread) {
|
|
386
|
-
if (!isOrchestratorThread(thread)) return false;
|
|
387
|
-
const title = thread.title?.trim() ?? "";
|
|
388
|
-
if (teamSlugFromName(title)) return false;
|
|
389
|
-
if (title === CLOUD_ORCHESTRATOR_GOAL) return true;
|
|
390
|
-
if (!title || title === "Untitled") return true;
|
|
391
|
-
if (thread.userSetTitle) return false;
|
|
392
|
-
if (thread.sourceRef?.trim() && title === thread.sourceRef.trim()) return true;
|
|
393
|
-
return false;
|
|
394
|
-
}
|
|
395
|
-
function takenTeamSlugsForOrchestration() {
|
|
396
|
-
const taken = /* @__PURE__ */ new Set(["global"]);
|
|
397
|
-
for (const thread of listThreads({ includeArchived: true })) {
|
|
398
|
-
if (thread.status === "archived") continue;
|
|
399
|
-
for (const slug of takenSlugsFromThread(thread)) {
|
|
400
|
-
taken.add(slug);
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
return [...taken];
|
|
404
|
-
}
|
|
405
|
-
function createGlobalChat(opts) {
|
|
406
|
-
ensureGlobalCoordinatorCwd();
|
|
407
|
-
const isCloud = opts.sourceRef === CLOUD_ORCHESTRATOR_GOAL || opts.title?.trim() === CLOUD_ORCHESTRATOR_GOAL;
|
|
408
|
-
const explicit = opts.title?.trim();
|
|
409
|
-
const title = explicit && explicit !== CLOUD_ORCHESTRATOR_GOAL ? explicit : allocateTeamName(takenTeamSlugsForOrchestration()).name;
|
|
410
|
-
const sourceRef = opts.sourceRef?.trim() || (isCloud ? CLOUD_ORCHESTRATOR_GOAL : title);
|
|
411
|
-
const resolved = resolveNewThreadOptions({
|
|
412
|
-
agent: opts.agent,
|
|
413
|
-
model: opts.model,
|
|
414
|
-
effort: opts.effort,
|
|
415
|
-
fast: opts.fast
|
|
416
|
-
});
|
|
417
|
-
const agent = assertOrchestratorCapableAgent(resolved.agent);
|
|
418
|
-
const worktreePath = globalAgentCwd();
|
|
419
|
-
const thread = createEmptyThread({
|
|
420
|
-
title,
|
|
421
|
-
// Stick nicknames the same way chat tabs do (avoid later sync overwrites).
|
|
422
|
-
userSetTitle: true,
|
|
423
|
-
sourceType: "orchestration",
|
|
424
|
-
sourceRef,
|
|
425
|
-
branchName: "global",
|
|
426
|
-
worktreePath,
|
|
427
|
-
repoPath: GLOBAL_WORKSPACE_ID,
|
|
428
|
-
agent,
|
|
429
|
-
autonomy: opts.autonomy ?? "default",
|
|
430
|
-
model: resolved.model,
|
|
431
|
-
effort: resolved.effort,
|
|
432
|
-
fast: resolved.fast,
|
|
433
|
-
planMode: Boolean(opts.planMode),
|
|
434
|
-
attachments: persistPendingFileAttachments(
|
|
435
|
-
worktreePath,
|
|
436
|
-
opts.attachments ?? []
|
|
437
|
-
),
|
|
438
|
-
parentThreadId: opts.parentThreadId ?? null,
|
|
439
|
-
status: "idle"
|
|
440
|
-
});
|
|
441
|
-
writeThread(thread);
|
|
442
|
-
return thread;
|
|
443
|
-
}
|
|
444
|
-
function healOrchestrationSoccerTitles() {
|
|
445
|
-
let healed = 0;
|
|
446
|
-
const taken = new Set(takenTeamSlugsForOrchestration());
|
|
447
|
-
for (const thread of listThreads({ includeArchived: true })) {
|
|
448
|
-
if (thread.status === "archived") continue;
|
|
449
|
-
if (!orchestrationTitleNeedsSoccerNickname(thread)) continue;
|
|
450
|
-
const team = allocateTeamName(taken);
|
|
451
|
-
taken.add(team.slug);
|
|
452
|
-
updateThread(thread.id, { title: team.name, userSetTitle: true });
|
|
453
|
-
healed += 1;
|
|
454
|
-
}
|
|
455
|
-
return healed;
|
|
456
|
-
}
|
|
457
|
-
function listGlobalThreads(includeArchived = false) {
|
|
458
|
-
return listThreads({ includeArchived }).filter(
|
|
459
|
-
(t) => t.repoPath === GLOBAL_WORKSPACE_ID
|
|
460
|
-
);
|
|
461
|
-
}
|
|
462
|
-
function findCloudCoordinator() {
|
|
463
|
-
return listThreads({ includeArchived: true }).find(
|
|
464
|
-
(t) => t.status !== "archived" && isCloudCoordinatorThread(t)
|
|
465
|
-
);
|
|
466
|
-
}
|
|
467
|
-
function slackCoordinatorSourceRef(teamId, userId) {
|
|
468
|
-
const team = teamId.trim();
|
|
469
|
-
const user = userId.trim();
|
|
470
|
-
if (!team || !user) {
|
|
471
|
-
throw new Error("Slack coordinator needs teamId and userId");
|
|
472
|
-
}
|
|
473
|
-
return `slack:${team}:${user}`;
|
|
474
|
-
}
|
|
475
|
-
function isSlackCoordinatorThread(thread) {
|
|
476
|
-
const ref = thread.sourceRef?.trim() ?? "";
|
|
477
|
-
if (!ref.startsWith("slack:")) return false;
|
|
478
|
-
return isGlobalThread(thread) || thread.sourceType === "orchestration";
|
|
479
|
-
}
|
|
480
|
-
function findSlackCoordinator(teamId, userId) {
|
|
481
|
-
const ref = slackCoordinatorSourceRef(teamId, userId);
|
|
482
|
-
return listThreads({ includeArchived: true }).find(
|
|
483
|
-
(t) => t.status !== "archived" && t.sourceRef === ref && isSlackCoordinatorThread(t)
|
|
484
|
-
);
|
|
485
|
-
}
|
|
486
|
-
function ensureSlackCoordinator(teamId, userId, agent, opts) {
|
|
487
|
-
const defaults = resolveThreadDefaults();
|
|
488
|
-
const desired = assertOrchestratorCapableAgent(agent);
|
|
489
|
-
const ref = slackCoordinatorSourceRef(teamId, userId);
|
|
490
|
-
if (!opts?.forceNew) {
|
|
491
|
-
const existing = findSlackCoordinator(teamId, userId);
|
|
492
|
-
if (existing) {
|
|
493
|
-
const patch = {};
|
|
494
|
-
if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
|
|
495
|
-
patch.repoPath = GLOBAL_WORKSPACE_ID;
|
|
496
|
-
patch.worktreePath = globalAgentCwd();
|
|
497
|
-
patch.branchName = "global";
|
|
498
|
-
}
|
|
499
|
-
const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
|
|
500
|
-
const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
|
|
501
|
-
if (canRetarget) {
|
|
502
|
-
if (existing.agent !== desired) patch.agent = desired;
|
|
503
|
-
if (existing.model !== defaults.model) patch.model = defaults.model;
|
|
504
|
-
if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
|
|
505
|
-
if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
|
|
506
|
-
}
|
|
507
|
-
if (Object.keys(patch).length > 0) {
|
|
508
|
-
return updateThread(existing.id, patch);
|
|
509
|
-
}
|
|
510
|
-
return existing;
|
|
511
|
-
}
|
|
512
|
-
}
|
|
513
|
-
return createGlobalChat({
|
|
514
|
-
sourceRef: ref,
|
|
515
|
-
agent: desired,
|
|
516
|
-
model: defaults.model,
|
|
517
|
-
effort: defaults.effort,
|
|
518
|
-
fast: defaults.fast
|
|
519
|
-
});
|
|
520
|
-
}
|
|
521
|
-
function ensureCloudCoordinator(agent) {
|
|
522
|
-
const defaults = resolveThreadDefaults();
|
|
523
|
-
const desired = assertOrchestratorCapableAgent(agent);
|
|
524
|
-
const existing = findCloudCoordinator();
|
|
525
|
-
if (existing) {
|
|
526
|
-
const patch = {};
|
|
527
|
-
if (existing.repoPath !== GLOBAL_WORKSPACE_ID) {
|
|
528
|
-
patch.repoPath = GLOBAL_WORKSPACE_ID;
|
|
529
|
-
patch.worktreePath = globalAgentCwd();
|
|
530
|
-
patch.branchName = "global";
|
|
531
|
-
}
|
|
532
|
-
const hasAgentTurns = existing.messages.some((m) => m.role === "agent");
|
|
533
|
-
const canRetarget = !existing.sessionId && !hasAgentTurns && existing.status !== "running" && existing.status !== "queued";
|
|
534
|
-
if (canRetarget) {
|
|
535
|
-
if (existing.agent !== desired) patch.agent = desired;
|
|
536
|
-
if (existing.model !== defaults.model) patch.model = defaults.model;
|
|
537
|
-
if (existing.effort !== defaults.effort) patch.effort = defaults.effort;
|
|
538
|
-
if (existing.fast !== defaults.fast) patch.fast = defaults.fast;
|
|
539
|
-
}
|
|
540
|
-
if (Object.keys(patch).length > 0) {
|
|
541
|
-
return updateThread(existing.id, patch);
|
|
542
|
-
}
|
|
543
|
-
return existing;
|
|
544
|
-
}
|
|
545
|
-
const created = createGlobalChat({
|
|
546
|
-
sourceRef: CLOUD_ORCHESTRATOR_GOAL,
|
|
547
|
-
agent: desired,
|
|
548
|
-
model: defaults.model,
|
|
549
|
-
effort: defaults.effort,
|
|
550
|
-
fast: defaults.fast
|
|
551
|
-
});
|
|
552
|
-
const all = listThreads({ includeArchived: true }).filter(
|
|
553
|
-
(t) => t.status !== "archived" && isCloudCoordinatorThread(t)
|
|
554
|
-
).sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
555
|
-
return all[0] ?? created;
|
|
556
|
-
}
|
|
557
|
-
|
|
558
|
-
export {
|
|
559
|
-
ORCHESTRATOR_AGENT_KINDS,
|
|
560
|
-
isOrchestratorCapableAgent,
|
|
561
|
-
assertOrchestratorCapableAgent,
|
|
562
|
-
coerceOrchestratorAgent,
|
|
563
|
-
CLOUD_ORCHESTRATOR_GOAL,
|
|
564
|
-
SIDEBOARD_FORCE_STOP,
|
|
565
|
-
CLOUD_COORDINATOR_BUSY_REPLY,
|
|
566
|
-
CLOUD_COORDINATOR_STOPPED_REPLY,
|
|
567
|
-
CLOUD_COORDINATOR_TIMEOUT_REPLY,
|
|
568
|
-
parseForceStopMessage,
|
|
569
|
-
isImageFilePath,
|
|
570
|
-
attachmentFromAbsolutePath,
|
|
571
|
-
stageAbsolutePathsAsAttachments,
|
|
572
|
-
stageBuffersAsAttachments,
|
|
573
|
-
attachmentsFromBuffers,
|
|
574
|
-
persistPendingFileAttachments,
|
|
575
|
-
attachmentsFromWorktreePaths,
|
|
576
|
-
GLOBAL_WORKSPACE_ID,
|
|
577
|
-
isGlobalThread,
|
|
578
|
-
isGlobalRepoPath,
|
|
579
|
-
isOrchestratorThread,
|
|
580
|
-
orchestratorSessionPoisonedByBuiltins,
|
|
581
|
-
isCloudCoordinatorThread,
|
|
582
|
-
orchestrationTitleNeedsSoccerNickname,
|
|
583
|
-
takenTeamSlugsForOrchestration,
|
|
584
|
-
createGlobalChat,
|
|
585
|
-
healOrchestrationSoccerTitles,
|
|
586
|
-
listGlobalThreads,
|
|
587
|
-
slackCoordinatorSourceRef,
|
|
588
|
-
isSlackCoordinatorThread,
|
|
589
|
-
findSlackCoordinator,
|
|
590
|
-
ensureSlackCoordinator,
|
|
591
|
-
ensureCloudCoordinator
|
|
592
|
-
};
|
package/dist/chunk-K2ANSHUO.js
DELETED
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
isGlobalRepoPath
|
|
3
|
-
} from "./chunk-G4MTYUWS.js";
|
|
4
|
-
import {
|
|
5
|
-
ensureGhPreferOrigin,
|
|
6
|
-
resolveRepoRoot
|
|
7
|
-
} from "./chunk-GE7M3QTE.js";
|
|
8
|
-
import {
|
|
9
|
-
appDataDir
|
|
10
|
-
} from "./chunk-QZQEXME2.js";
|
|
11
|
-
|
|
12
|
-
// src/store/workspaces.ts
|
|
13
|
-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
14
|
-
import { basename, join } from "path";
|
|
15
|
-
function workspacesFile() {
|
|
16
|
-
return join(appDataDir(), "workspaces.json");
|
|
17
|
-
}
|
|
18
|
-
function removedWorkspacesFile() {
|
|
19
|
-
return join(appDataDir(), "removed-workspaces.json");
|
|
20
|
-
}
|
|
21
|
-
function readAll() {
|
|
22
|
-
const path = workspacesFile();
|
|
23
|
-
if (!existsSync(path)) return [];
|
|
24
|
-
try {
|
|
25
|
-
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
26
|
-
return Array.isArray(raw) ? raw : [];
|
|
27
|
-
} catch {
|
|
28
|
-
return [];
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
function writeAll(list) {
|
|
32
|
-
mkdirSync(appDataDir(), { recursive: true });
|
|
33
|
-
writeFileSync(workspacesFile(), JSON.stringify(list, null, 2), "utf8");
|
|
34
|
-
}
|
|
35
|
-
function readRemoved() {
|
|
36
|
-
const path = removedWorkspacesFile();
|
|
37
|
-
if (!existsSync(path)) return /* @__PURE__ */ new Set();
|
|
38
|
-
try {
|
|
39
|
-
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
40
|
-
return new Set(Array.isArray(raw) ? raw.filter((p) => typeof p === "string") : []);
|
|
41
|
-
} catch {
|
|
42
|
-
return /* @__PURE__ */ new Set();
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
function writeRemoved(paths) {
|
|
46
|
-
mkdirSync(appDataDir(), { recursive: true });
|
|
47
|
-
writeFileSync(removedWorkspacesFile(), JSON.stringify([...paths].sort(), null, 2), "utf8");
|
|
48
|
-
}
|
|
49
|
-
function rememberRemoved(repoPath) {
|
|
50
|
-
const next = readRemoved();
|
|
51
|
-
next.add(repoPath);
|
|
52
|
-
writeRemoved(next);
|
|
53
|
-
}
|
|
54
|
-
function forgetRemoved(repoPath) {
|
|
55
|
-
const next = readRemoved();
|
|
56
|
-
if (!next.delete(repoPath)) return;
|
|
57
|
-
writeRemoved(next);
|
|
58
|
-
}
|
|
59
|
-
function listWorkspaces() {
|
|
60
|
-
const all = readAll();
|
|
61
|
-
const valid = all.filter(
|
|
62
|
-
(w) => Boolean(w.path) && w.path !== "/" && w.path !== "." && !isGlobalRepoPath(w.path)
|
|
63
|
-
);
|
|
64
|
-
if (valid.length !== all.length) writeAll(valid);
|
|
65
|
-
return valid.sort((a, b) => a.name.localeCompare(b.name));
|
|
66
|
-
}
|
|
67
|
-
async function addWorkspace(repoPath) {
|
|
68
|
-
const root = await resolveRepoRoot(repoPath);
|
|
69
|
-
if (!root || root === "/") throw new Error(`Invalid repo path: ${repoPath}`);
|
|
70
|
-
if (!existsSync(root)) throw new Error(`Repo not found: ${root}`);
|
|
71
|
-
forgetRemoved(root);
|
|
72
|
-
await ensureGhPreferOrigin(root);
|
|
73
|
-
const current = readAll();
|
|
74
|
-
const existing = current.find((w) => w.path === root);
|
|
75
|
-
if (existing) return existing;
|
|
76
|
-
const next = {
|
|
77
|
-
path: root,
|
|
78
|
-
name: basename(root),
|
|
79
|
-
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
80
|
-
};
|
|
81
|
-
writeAll([...current, next]);
|
|
82
|
-
return next;
|
|
83
|
-
}
|
|
84
|
-
function removeWorkspace(repoPath) {
|
|
85
|
-
writeAll(readAll().filter((w) => w.path !== repoPath));
|
|
86
|
-
rememberRemoved(repoPath);
|
|
87
|
-
}
|
|
88
|
-
async function ensureWorkspace(repoPath) {
|
|
89
|
-
return addWorkspace(repoPath);
|
|
90
|
-
}
|
|
91
|
-
function syncWorkspacesFromThreads(repoPaths) {
|
|
92
|
-
const current = readAll();
|
|
93
|
-
const removed = readRemoved();
|
|
94
|
-
const byPath = new Map(current.map((w) => [w.path, w]));
|
|
95
|
-
let dirty = false;
|
|
96
|
-
for (const path of repoPaths) {
|
|
97
|
-
if (!path || path === "/" || isGlobalRepoPath(path) || byPath.has(path) || removed.has(path)) {
|
|
98
|
-
continue;
|
|
99
|
-
}
|
|
100
|
-
if (!existsSync(path)) continue;
|
|
101
|
-
const ws = {
|
|
102
|
-
path,
|
|
103
|
-
name: basename(path),
|
|
104
|
-
addedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
105
|
-
};
|
|
106
|
-
byPath.set(path, ws);
|
|
107
|
-
dirty = true;
|
|
108
|
-
}
|
|
109
|
-
const next = [...byPath.values()];
|
|
110
|
-
if (dirty) writeAll(next);
|
|
111
|
-
return next.sort((a, b) => a.name.localeCompare(b.name));
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export {
|
|
115
|
-
listWorkspaces,
|
|
116
|
-
addWorkspace,
|
|
117
|
-
removeWorkspace,
|
|
118
|
-
ensureWorkspace,
|
|
119
|
-
syncWorkspacesFromThreads
|
|
120
|
-
};
|