@sideboard-ai/core 0.1.135 → 0.1.136
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-O3AJMI2Y.js → agents-ELWR7A2T.js} +3 -3
- package/dist/{agents-RTQFF7PY.js → agents-QNTTLMG2.js} +3 -3
- package/dist/{chunk-RDULVW3E.js → chunk-4XKUHP6G.js} +1 -1
- package/dist/{chunk-N62K3KXX.js → chunk-CYM5DCHI.js} +38 -4
- package/dist/{chunk-XUEI4GCF.js → chunk-GSKRGF7B.js} +284 -3
- package/dist/{chunk-57GIFU3X.js → chunk-IFZ4MOTN.js} +2 -2
- package/dist/{chunk-KBBXNS2V.js → chunk-JPBRMUM6.js} +8 -4
- package/dist/{chunk-2ESCEK2Q.js → chunk-K5YT5GX2.js} +242 -3
- package/dist/{chunk-LOKXPQ4U.js → chunk-MDCKV2NF.js} +1 -1
- package/dist/{chunk-XIKEUCNC.js → chunk-TIGKDMIA.js} +139 -266
- package/dist/{chunk-K7EX47QG.js → chunk-TQ4S5AGJ.js} +2 -2
- package/dist/{chunk-Z5LYMW7M.js → chunk-WS5LFFU3.js} +135 -217
- package/dist/{coordinator-prompt-Y737IIFR.js → coordinator-prompt-2OWSUAUR.js} +1 -1
- package/dist/{coordinator-prompt-FYMWE33S.js → coordinator-prompt-IPL4Z6SL.js} +1 -1
- package/dist/{global-workspace-6KH6BSKL.js → global-workspace-JDUCUL7S.js} +2 -2
- package/dist/{global-workspace-ZFKNLBZA.js → global-workspace-NIKZAKOO.js} +2 -2
- package/dist/index.cjs +828 -615
- package/dist/index.d.cts +24 -1
- package/dist/index.d.ts +24 -1
- package/dist/index.js +38 -17
- package/dist/mcp/run-stdio.cjs +657 -485
- package/dist/mcp/run-stdio.js +20 -9
- package/dist/{orchestrator-3YDPPZHZ.js → orchestrator-6I47JMU2.js} +5 -5
- package/dist/{orchestrator-2BRAPJ47.js → orchestrator-KK3CUW37.js} +5 -5
- package/dist/{workspaces-3RRF3LVF.js → workspaces-5EWNNALF.js} +3 -3
- package/dist/{workspaces-AYI5DHK4.js → workspaces-KZA3TCEE.js} +3 -3
- package/package.json +1 -1
|
@@ -34,7 +34,7 @@ import {
|
|
|
34
34
|
resolveLoginCommand,
|
|
35
35
|
resolveQuotaFallbackAgent,
|
|
36
36
|
turnCostUsdFromCursorUsage
|
|
37
|
-
} from "./chunk-
|
|
37
|
+
} from "./chunk-JPBRMUM6.js";
|
|
38
38
|
import "./chunk-ED4UPEJX.js";
|
|
39
39
|
import "./chunk-S42XV45P.js";
|
|
40
40
|
import "./chunk-6GN5WPYZ.js";
|
|
@@ -43,8 +43,8 @@ import {
|
|
|
43
43
|
assertOrchestratorCapableAgent,
|
|
44
44
|
coerceOrchestratorAgent,
|
|
45
45
|
isOrchestratorCapableAgent
|
|
46
|
-
} from "./chunk-
|
|
47
|
-
import "./chunk-
|
|
46
|
+
} from "./chunk-K5YT5GX2.js";
|
|
47
|
+
import "./chunk-TQ4S5AGJ.js";
|
|
48
48
|
import "./chunk-QAV3HGVS.js";
|
|
49
49
|
import "./chunk-B3SJXYIJ.js";
|
|
50
50
|
import "./chunk-J5IBSVB3.js";
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
resolveCursorModelId,
|
|
29
29
|
resolveLoginCommand,
|
|
30
30
|
resolveQuotaFallbackAgent
|
|
31
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-CYM5DCHI.js";
|
|
32
32
|
import "./chunk-KBWND62T.js";
|
|
33
33
|
import "./chunk-M267JPEA.js";
|
|
34
34
|
import {
|
|
@@ -36,8 +36,8 @@ import {
|
|
|
36
36
|
assertOrchestratorCapableAgent,
|
|
37
37
|
coerceOrchestratorAgent,
|
|
38
38
|
isOrchestratorCapableAgent
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
39
|
+
} from "./chunk-GSKRGF7B.js";
|
|
40
|
+
import "./chunk-IFZ4MOTN.js";
|
|
41
41
|
import "./chunk-ELBYOGVA.js";
|
|
42
42
|
import {
|
|
43
43
|
cursorSdkMessageToEvents,
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./chunk-M267JPEA.js";
|
|
10
10
|
import {
|
|
11
11
|
isOrchestratorThread
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-GSKRGF7B.js";
|
|
13
13
|
import {
|
|
14
14
|
applyAgentRunnerHeapEnv,
|
|
15
15
|
applyNodeLaunch,
|
|
@@ -580,14 +580,47 @@ function asRecord(input) {
|
|
|
580
580
|
function str(v) {
|
|
581
581
|
return typeof v === "string" && v.trim() ? v : void 0;
|
|
582
582
|
}
|
|
583
|
+
function looksLikeFilePath(value) {
|
|
584
|
+
if (value.startsWith("/") || value.startsWith("~/")) return true;
|
|
585
|
+
if (/^[A-Za-z]:[\\/]/.test(value)) return true;
|
|
586
|
+
return value.includes("/") || value.includes("\\");
|
|
587
|
+
}
|
|
588
|
+
function stripWorktreePrefix(path, worktreePath) {
|
|
589
|
+
if (!worktreePath) return path;
|
|
590
|
+
const prefix = worktreePath.replace(/[/\\]+$/, "");
|
|
591
|
+
if (path === prefix || path === `${prefix}/`) return "";
|
|
592
|
+
if (path.startsWith(`${prefix}/`)) return path.slice(prefix.length + 1);
|
|
593
|
+
return path;
|
|
594
|
+
}
|
|
595
|
+
function visibleToolRowDetail(detail, description, worktreePath) {
|
|
596
|
+
if (!detail?.trim()) return void 0;
|
|
597
|
+
const raw = detail.trim();
|
|
598
|
+
const desc = (description ?? "").trim();
|
|
599
|
+
if (!looksLikeFilePath(raw)) {
|
|
600
|
+
if (desc === raw) return void 0;
|
|
601
|
+
return raw;
|
|
602
|
+
}
|
|
603
|
+
const rel = stripWorktreePrefix(raw, worktreePath);
|
|
604
|
+
if (!rel) return void 0;
|
|
605
|
+
const base = fileBasename(rel);
|
|
606
|
+
if (desc && (desc === base || desc.endsWith(` ${base}`))) return void 0;
|
|
607
|
+
if (rel.length <= 42) return rel;
|
|
608
|
+
const parts = rel.split(/[/\\]/).filter(Boolean);
|
|
609
|
+
if (parts.length >= 2) return `\u2026/${parts.slice(-2).join("/")}`;
|
|
610
|
+
return base;
|
|
611
|
+
}
|
|
583
612
|
function toolDetail(name, input) {
|
|
584
613
|
if (!input) return void 0;
|
|
585
614
|
const command = str(input.command) ?? str(input.cmd);
|
|
586
615
|
if (command) return command;
|
|
616
|
+
const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
|
|
617
|
+
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
618
|
+
if (isSearch && pattern) {
|
|
619
|
+
return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
620
|
+
}
|
|
587
621
|
const path = str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
|
|
588
622
|
if (path) return path;
|
|
589
|
-
|
|
590
|
-
if (pattern) return pattern;
|
|
623
|
+
if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
591
624
|
const query = str(input.query) ?? str(input.prompt);
|
|
592
625
|
if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
|
|
593
626
|
try {
|
|
@@ -1695,7 +1728,7 @@ var claudeAdapter = {
|
|
|
1695
1728
|
);
|
|
1696
1729
|
}
|
|
1697
1730
|
const mode = permissionMode(thread);
|
|
1698
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
1731
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-NIKZAKOO.js");
|
|
1699
1732
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
1700
1733
|
const injectedServers = await buildInjectedMcpServers({
|
|
1701
1734
|
includeSideboard: true,
|
|
@@ -3259,6 +3292,7 @@ export {
|
|
|
3259
3292
|
sanitizeMcpServerName,
|
|
3260
3293
|
mcpAllowTools,
|
|
3261
3294
|
mcpAuthWarnings,
|
|
3295
|
+
visibleToolRowDetail,
|
|
3262
3296
|
toolDetail,
|
|
3263
3297
|
toolDescription,
|
|
3264
3298
|
isSubagentToolName,
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ensureGlobalCoordinatorCwd
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IFZ4MOTN.js";
|
|
4
4
|
import {
|
|
5
5
|
allocateTeamName,
|
|
6
6
|
takenSlugsFromThread,
|
|
7
7
|
teamSlugFromName
|
|
8
8
|
} from "./chunk-HQQNLDVC.js";
|
|
9
|
+
import {
|
|
10
|
+
ATTACHMENTS_DIR,
|
|
11
|
+
attachmentsGitignoreBody
|
|
12
|
+
} from "./chunk-FKOIHGKV.js";
|
|
9
13
|
import {
|
|
10
14
|
resolveNewThreadOptions,
|
|
11
15
|
resolveThreadDefaults
|
|
@@ -50,6 +54,272 @@ function parseForceStopMessage(message) {
|
|
|
50
54
|
return { forceStop, remainder: forceStop ? remainder : message };
|
|
51
55
|
}
|
|
52
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
|
+
|
|
53
323
|
// src/agents/orchestrator-capable.ts
|
|
54
324
|
var ORCHESTRATOR_AGENT_KINDS = [
|
|
55
325
|
"claude",
|
|
@@ -145,6 +415,7 @@ function createGlobalChat(opts) {
|
|
|
145
415
|
fast: opts.fast
|
|
146
416
|
});
|
|
147
417
|
const agent = assertOrchestratorCapableAgent(resolved.agent);
|
|
418
|
+
const worktreePath = globalAgentCwd();
|
|
148
419
|
const thread = createEmptyThread({
|
|
149
420
|
title,
|
|
150
421
|
// Stick nicknames the same way chat tabs do (avoid later sync overwrites).
|
|
@@ -152,7 +423,7 @@ function createGlobalChat(opts) {
|
|
|
152
423
|
sourceType: "orchestration",
|
|
153
424
|
sourceRef,
|
|
154
425
|
branchName: "global",
|
|
155
|
-
worktreePath
|
|
426
|
+
worktreePath,
|
|
156
427
|
repoPath: GLOBAL_WORKSPACE_ID,
|
|
157
428
|
agent,
|
|
158
429
|
autonomy: opts.autonomy ?? "default",
|
|
@@ -160,7 +431,10 @@ function createGlobalChat(opts) {
|
|
|
160
431
|
effort: resolved.effort,
|
|
161
432
|
fast: resolved.fast,
|
|
162
433
|
planMode: Boolean(opts.planMode),
|
|
163
|
-
attachments:
|
|
434
|
+
attachments: persistPendingFileAttachments(
|
|
435
|
+
worktreePath,
|
|
436
|
+
opts.attachments ?? []
|
|
437
|
+
),
|
|
164
438
|
parentThreadId: opts.parentThreadId ?? null,
|
|
165
439
|
status: "idle"
|
|
166
440
|
});
|
|
@@ -292,6 +566,13 @@ export {
|
|
|
292
566
|
CLOUD_COORDINATOR_STOPPED_REPLY,
|
|
293
567
|
CLOUD_COORDINATOR_TIMEOUT_REPLY,
|
|
294
568
|
parseForceStopMessage,
|
|
569
|
+
isImageFilePath,
|
|
570
|
+
attachmentFromAbsolutePath,
|
|
571
|
+
stageAbsolutePathsAsAttachments,
|
|
572
|
+
stageBuffersAsAttachments,
|
|
573
|
+
attachmentsFromBuffers,
|
|
574
|
+
persistPendingFileAttachments,
|
|
575
|
+
attachmentsFromWorktreePaths,
|
|
295
576
|
GLOBAL_WORKSPACE_ID,
|
|
296
577
|
isGlobalThread,
|
|
297
578
|
isGlobalRepoPath,
|
|
@@ -64,7 +64,7 @@ var COORDINATOR_TOOL_PLAYBOOK = [
|
|
|
64
64
|
"- fork_worktree \u2014 fork a worktree chat into a NEW git worktree + chat (transcript attached); optional agent; leave model unset (Auto) unless you have a reason. Not for orchestration chats.",
|
|
65
65
|
"- fork_chat \u2014 fork a worktree chat (same worktree tab) OR a Global orchestration chat (new orchestration tab); optional agent; leave model unset (Auto) unless you have a reason. Remote coordinators: use this to continue another orchestration chat on a different agent after session limits.",
|
|
66
66
|
"- send_to_thread \u2014 queue a prompt (start/continue a chat turn); pass force_stop: true to interrupt mid-turn / clear stale queued prompts before replacing with a new request",
|
|
67
|
-
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success.",
|
|
67
|
+
"- wait_for_turn / get_turn_result \u2014 wait for and read the agent reply (includes last-turn usage / costUsd when the child agent reported it). wait_for_turn returns within ~45s even if the child is still working (MCP clients kill longer tool calls). If stillRunning is true, progress is a live snapshot of tools/thinking \u2014 call wait_for_turn again. status=queued with no lastActivityAt means the child has not started yet (concurrency cap) \u2014 keep waiting; do not force_stop or send a check-in. Do not send \u201Care you stuck?\u201D or assume a hang while lastActivityAt is recent. On status error, lastError (and text) is the failure \u2014 switch agent, tell the user, or retry; do not treat empty text as success. On status stopped or broken (or incomplete=true), the child was interrupted or died \u2014 resume with send_to_thread or tell the user; never treat stopped as a finished turn. Sideboard also injects a notice into this chat when a child stops unexpectedly.",
|
|
68
68
|
"- stop_thread \u2014 force-stop: kill in-flight turn AND clear queued prompts (do not leave stale queue after an interrupt)",
|
|
69
69
|
"- archive_thread / restore_thread \u2014 archive (tears down worktree when last tab) or restore",
|
|
70
70
|
"Setup / run:",
|
|
@@ -104,7 +104,7 @@ function coordinatorTurnReminder(opts) {
|
|
|
104
104
|
`- YOUR orchestration thread id is ${opts.parentId} \u2014 pass parentThreadId="${opts.parentId}" on create_thread, or omit it.`,
|
|
105
105
|
goal ? `- Goal / title: ${goal}` : null,
|
|
106
106
|
accountDefaultsPlaybookLine(),
|
|
107
|
-
"- Status: list_board (worktree Kanban: New \u2192 Draft \u2192 Review \u2192 Merged) or list_threads. Link chats as `[Title](sideboard://thread/<id>)`. Merge only if the user asked."
|
|
107
|
+
"- Status: list_board (worktree Kanban: New \u2192 Draft \u2192 Review \u2192 Merged) or list_threads. Link chats as `[Title](sideboard://thread/<id>)`. Merge only if the user asked. If a child is stopped/error/broken, it did not finish \u2014 resume or tell the user."
|
|
108
108
|
].filter(Boolean).join("\n");
|
|
109
109
|
}
|
|
110
110
|
function ensureGlobalCoordinatorCwd(opts) {
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
} from "./chunk-S42XV45P.js";
|
|
12
12
|
import {
|
|
13
13
|
isOrchestratorThread
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-K5YT5GX2.js";
|
|
15
15
|
import {
|
|
16
16
|
codexUnattendedGitConfigArgs,
|
|
17
17
|
mergeAgentGitAuthEnv,
|
|
@@ -773,10 +773,14 @@ function toolDetail(name, input) {
|
|
|
773
773
|
if (!input) return void 0;
|
|
774
774
|
const command = str(input.command) ?? str(input.cmd);
|
|
775
775
|
if (command) return command;
|
|
776
|
+
const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
|
|
777
|
+
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
778
|
+
if (isSearch && pattern) {
|
|
779
|
+
return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
780
|
+
}
|
|
776
781
|
const path = str(input.file_path) ?? str(input.path) ?? str(input.filePath) ?? str(input.filename);
|
|
777
782
|
if (path) return path;
|
|
778
|
-
|
|
779
|
-
if (pattern) return pattern;
|
|
783
|
+
if (pattern) return pattern.length > 80 ? `${pattern.slice(0, 77)}\u2026` : pattern;
|
|
780
784
|
const query = str(input.query) ?? str(input.prompt);
|
|
781
785
|
if (query) return query.length > 80 ? `${query.slice(0, 77)}\u2026` : query;
|
|
782
786
|
try {
|
|
@@ -2042,7 +2046,7 @@ var claudeAdapter = {
|
|
|
2042
2046
|
);
|
|
2043
2047
|
}
|
|
2044
2048
|
const mode = permissionMode(thread);
|
|
2045
|
-
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-
|
|
2049
|
+
const { isOrchestratorThread: isOrchestratorThread2 } = await import("./global-workspace-JDUCUL7S.js");
|
|
2046
2050
|
const isOrchestrator = isOrchestratorThread2(thread);
|
|
2047
2051
|
const injectedServers = await buildInjectedMcpServers({
|
|
2048
2052
|
includeSideboard: true,
|