@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.
Files changed (27) hide show
  1. package/dist/{agents-O3AJMI2Y.js → agents-ELWR7A2T.js} +3 -3
  2. package/dist/{agents-RTQFF7PY.js → agents-QNTTLMG2.js} +3 -3
  3. package/dist/{chunk-RDULVW3E.js → chunk-4XKUHP6G.js} +1 -1
  4. package/dist/{chunk-N62K3KXX.js → chunk-CYM5DCHI.js} +38 -4
  5. package/dist/{chunk-XUEI4GCF.js → chunk-GSKRGF7B.js} +284 -3
  6. package/dist/{chunk-57GIFU3X.js → chunk-IFZ4MOTN.js} +2 -2
  7. package/dist/{chunk-KBBXNS2V.js → chunk-JPBRMUM6.js} +8 -4
  8. package/dist/{chunk-2ESCEK2Q.js → chunk-K5YT5GX2.js} +242 -3
  9. package/dist/{chunk-LOKXPQ4U.js → chunk-MDCKV2NF.js} +1 -1
  10. package/dist/{chunk-XIKEUCNC.js → chunk-TIGKDMIA.js} +139 -266
  11. package/dist/{chunk-K7EX47QG.js → chunk-TQ4S5AGJ.js} +2 -2
  12. package/dist/{chunk-Z5LYMW7M.js → chunk-WS5LFFU3.js} +135 -217
  13. package/dist/{coordinator-prompt-Y737IIFR.js → coordinator-prompt-2OWSUAUR.js} +1 -1
  14. package/dist/{coordinator-prompt-FYMWE33S.js → coordinator-prompt-IPL4Z6SL.js} +1 -1
  15. package/dist/{global-workspace-6KH6BSKL.js → global-workspace-JDUCUL7S.js} +2 -2
  16. package/dist/{global-workspace-ZFKNLBZA.js → global-workspace-NIKZAKOO.js} +2 -2
  17. package/dist/index.cjs +828 -615
  18. package/dist/index.d.cts +24 -1
  19. package/dist/index.d.ts +24 -1
  20. package/dist/index.js +38 -17
  21. package/dist/mcp/run-stdio.cjs +657 -485
  22. package/dist/mcp/run-stdio.js +20 -9
  23. package/dist/{orchestrator-3YDPPZHZ.js → orchestrator-6I47JMU2.js} +5 -5
  24. package/dist/{orchestrator-2BRAPJ47.js → orchestrator-KK3CUW37.js} +5 -5
  25. package/dist/{workspaces-3RRF3LVF.js → workspaces-5EWNNALF.js} +3 -3
  26. package/dist/{workspaces-AYI5DHK4.js → workspaces-KZA3TCEE.js} +3 -3
  27. package/package.json +1 -1
@@ -2,12 +2,16 @@
2
2
 
3
3
  import {
4
4
  ensureGlobalCoordinatorCwd
5
- } from "./chunk-K7EX47QG.js";
5
+ } from "./chunk-TQ4S5AGJ.js";
6
6
  import {
7
7
  allocateTeamName,
8
8
  takenSlugsFromThread,
9
9
  teamSlugFromName
10
10
  } from "./chunk-QAV3HGVS.js";
11
+ import {
12
+ ATTACHMENTS_DIR,
13
+ attachmentsGitignoreBody
14
+ } from "./chunk-B3SJXYIJ.js";
11
15
  import {
12
16
  createEmptyThread,
13
17
  listThreads,
@@ -44,6 +48,233 @@ var CLOUD_COORDINATOR_TIMEOUT_REPLY = [
44
48
  "What do you want me to do? (retry later, wait, force-stop, rephrase, or cancel)"
45
49
  ].join(" ");
46
50
 
51
+ // src/composer/stage-files.ts
52
+ import { copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from "fs";
53
+ import { basename, extname, join } from "path";
54
+ import { randomUUID } from "crypto";
55
+ var IMAGE_EXTENSIONS = /* @__PURE__ */ new Set([
56
+ "png",
57
+ "jpg",
58
+ "jpeg",
59
+ "gif",
60
+ "webp",
61
+ "svg",
62
+ "bmp",
63
+ "ico"
64
+ ]);
65
+ var IMAGE_MIME_BY_EXT = {
66
+ png: "image/png",
67
+ jpg: "image/jpeg",
68
+ jpeg: "image/jpeg",
69
+ gif: "image/gif",
70
+ webp: "image/webp",
71
+ svg: "image/svg+xml",
72
+ bmp: "image/bmp",
73
+ ico: "image/x-icon"
74
+ };
75
+ var MAX_INLINE_BYTES = 4e5;
76
+ var MAX_PREVIEW_BYTES = 5e6;
77
+ function fileExtension(filePath) {
78
+ const base = basename(filePath).toLowerCase();
79
+ return base.includes(".") ? base.split(".").pop() || "" : "";
80
+ }
81
+ function isImageFilePath(filePath) {
82
+ return IMAGE_EXTENSIONS.has(fileExtension(filePath));
83
+ }
84
+ function imageMimeType(filePath) {
85
+ return IMAGE_MIME_BY_EXT[fileExtension(filePath)] || "image/png";
86
+ }
87
+ function ensureAttachmentsDir(worktreePath) {
88
+ const dir = join(worktreePath, ATTACHMENTS_DIR);
89
+ mkdirSync(dir, { recursive: true });
90
+ const gi = join(dir, ".gitignore");
91
+ if (!existsSync(gi)) {
92
+ writeFileSync(gi, attachmentsGitignoreBody(), "utf8");
93
+ }
94
+ return dir;
95
+ }
96
+ function uniqueAttachmentName(dir, originalName) {
97
+ const safe = originalName.replace(/[/\\]/g, "_") || "file";
98
+ if (!existsSync(join(dir, safe))) return safe;
99
+ const ext = extname(safe);
100
+ const stem = ext ? safe.slice(0, -ext.length) : safe;
101
+ for (let i = 1; i < 1e4; i++) {
102
+ const candidate = `${stem}-${i}${ext}`;
103
+ if (!existsSync(join(dir, candidate))) return candidate;
104
+ }
105
+ return `${stem}-${randomUUID()}${ext}`;
106
+ }
107
+ function previewDataUrlFromBuf(filePath, buf) {
108
+ if (!isImageFilePath(filePath)) return void 0;
109
+ if (buf.length > MAX_PREVIEW_BYTES) return void 0;
110
+ return `data:${imageMimeType(filePath)};base64,${buf.toString("base64")}`;
111
+ }
112
+ function attachmentFromBuffer(name, buf, opts) {
113
+ const previewDataUrl = previewDataUrlFromBuf(name, buf);
114
+ if (isImageFilePath(name)) {
115
+ const pathHint = opts.path ? `\`${opts.path}\`` : opts.sourceLabel || name;
116
+ return {
117
+ id: randomUUID(),
118
+ name,
119
+ kind: "file",
120
+ path: opts.path,
121
+ previewDataUrl,
122
+ content: [
123
+ `Image attached: ${pathHint}`,
124
+ 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."
125
+ ].join("\n")
126
+ };
127
+ }
128
+ if (buf.length > MAX_INLINE_BYTES) {
129
+ return {
130
+ id: randomUUID(),
131
+ name,
132
+ kind: "file",
133
+ path: opts.path,
134
+ 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)`
135
+ };
136
+ }
137
+ if (buf.includes(0)) {
138
+ return {
139
+ id: randomUUID(),
140
+ name,
141
+ kind: "file",
142
+ path: opts.path,
143
+ content: opts.path ? `(binary file at \`${opts.path}\` \u2014 use tools to inspect)` : `(binary file attached by path only: ${opts.sourceLabel || name})`
144
+ };
145
+ }
146
+ return {
147
+ id: randomUUID(),
148
+ name,
149
+ kind: "file",
150
+ path: opts.path,
151
+ content: buf.toString("utf8")
152
+ };
153
+ }
154
+ function stageAbsolutePathsAsAttachments(worktreePath, absolutePaths) {
155
+ if (absolutePaths.length === 0) return [];
156
+ const dir = ensureAttachmentsDir(worktreePath);
157
+ const out = [];
158
+ for (const abs of absolutePaths) {
159
+ const originalName = basename(abs);
160
+ try {
161
+ const st = statSync(abs);
162
+ if (!st.isFile()) continue;
163
+ const name = uniqueAttachmentName(dir, originalName);
164
+ const destAbs = join(dir, name);
165
+ copyFileSync(abs, destAbs);
166
+ const rel = `${ATTACHMENTS_DIR}/${name}`;
167
+ const buf = readFileSync(destAbs);
168
+ out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
169
+ } catch (err) {
170
+ out.push({
171
+ id: randomUUID(),
172
+ name: originalName,
173
+ kind: "file",
174
+ content: `(could not attach ${abs}: ${err instanceof Error ? err.message : String(err)})`
175
+ });
176
+ }
177
+ }
178
+ return out;
179
+ }
180
+ function stageBuffersAsAttachments(worktreePath, buffers) {
181
+ if (buffers.length === 0) return [];
182
+ const dir = ensureAttachmentsDir(worktreePath);
183
+ const out = [];
184
+ for (const item of buffers) {
185
+ const originalName = (item.name || "file").replace(/[/\\]/g, "_") || "file";
186
+ try {
187
+ const buf = Buffer.from(item.dataBase64, "base64");
188
+ const name = uniqueAttachmentName(dir, originalName);
189
+ const destAbs = join(dir, name);
190
+ writeFileSync(destAbs, buf);
191
+ const rel = `${ATTACHMENTS_DIR}/${name}`;
192
+ out.push(attachmentFromBuffer(name, buf, { path: rel }));
193
+ } catch (err) {
194
+ out.push({
195
+ id: randomUUID(),
196
+ name: originalName,
197
+ kind: "file",
198
+ content: `(could not attach ${originalName}: ${err instanceof Error ? err.message : String(err)})`
199
+ });
200
+ }
201
+ }
202
+ return out;
203
+ }
204
+ function isWorktreeRelativePath(p) {
205
+ if (!p || p.includes("..")) return false;
206
+ if (p.startsWith("/")) return false;
207
+ if (/^[A-Za-z]:[\\/]/.test(p)) return false;
208
+ return true;
209
+ }
210
+ function dataUrlToBase64(url) {
211
+ if (!url) return null;
212
+ const m = /^data:[^;]+;base64,(.+)$/s.exec(url);
213
+ return m?.[1] ?? null;
214
+ }
215
+ var IMAGE_HINT_RE = /^Image attached:/;
216
+ var PLACEHOLDER_CONTENT_RE = /^\((could not |file too large|binary file|not a file|invalid path)/;
217
+ function persistPendingFileAttachments(worktreePath, attachments) {
218
+ if (attachments.length === 0) return attachments;
219
+ const keep = [];
220
+ const buffers = [];
221
+ for (const att of attachments) {
222
+ if (att.kind !== "file") {
223
+ keep.push(att);
224
+ continue;
225
+ }
226
+ if (att.path && isWorktreeRelativePath(att.path)) {
227
+ keep.push(att);
228
+ continue;
229
+ }
230
+ const fromPreview = dataUrlToBase64(att.previewDataUrl);
231
+ if (fromPreview) {
232
+ buffers.push({ name: att.name, dataBase64: fromPreview });
233
+ continue;
234
+ }
235
+ if (att.content && !IMAGE_HINT_RE.test(att.content) && !PLACEHOLDER_CONTENT_RE.test(att.content)) {
236
+ buffers.push({
237
+ name: att.name,
238
+ dataBase64: Buffer.from(att.content, "utf8").toString("base64")
239
+ });
240
+ continue;
241
+ }
242
+ keep.push(att);
243
+ }
244
+ if (buffers.length === 0) return attachments;
245
+ return [...keep, ...stageBuffersAsAttachments(worktreePath, buffers)];
246
+ }
247
+ function attachmentsFromWorktreePaths(worktreePath, relativePaths) {
248
+ const out = [];
249
+ for (const rel of relativePaths) {
250
+ if (!rel || rel.includes("..") || rel.startsWith("/")) {
251
+ out.push({
252
+ id: randomUUID(),
253
+ name: basename(rel) || "file",
254
+ kind: "file",
255
+ content: `(invalid path: ${rel})`
256
+ });
257
+ continue;
258
+ }
259
+ const name = basename(rel);
260
+ try {
261
+ const abs = join(worktreePath, rel);
262
+ const st = statSync(abs);
263
+ if (!st.isFile()) continue;
264
+ const buf = readFileSync(abs);
265
+ out.push(attachmentFromBuffer(name, buf, { path: rel, sourceLabel: abs }));
266
+ } catch (err) {
267
+ out.push({
268
+ id: randomUUID(),
269
+ name,
270
+ kind: "file",
271
+ content: `(could not read ${rel}: ${err instanceof Error ? err.message : String(err)})`
272
+ });
273
+ }
274
+ }
275
+ return out;
276
+ }
277
+
47
278
  // src/agents/orchestrator-capable.ts
48
279
  var ORCHESTRATOR_AGENT_KINDS = [
49
280
  "claude",
@@ -139,6 +370,7 @@ function createGlobalChat(opts) {
139
370
  fast: opts.fast
140
371
  });
141
372
  const agent = assertOrchestratorCapableAgent(resolved.agent);
373
+ const worktreePath = globalAgentCwd();
142
374
  const thread = createEmptyThread({
143
375
  title,
144
376
  // Stick nicknames the same way chat tabs do (avoid later sync overwrites).
@@ -146,7 +378,7 @@ function createGlobalChat(opts) {
146
378
  sourceType: "orchestration",
147
379
  sourceRef,
148
380
  branchName: "global",
149
- worktreePath: globalAgentCwd(),
381
+ worktreePath,
150
382
  repoPath: GLOBAL_WORKSPACE_ID,
151
383
  agent,
152
384
  autonomy: opts.autonomy ?? "default",
@@ -154,7 +386,10 @@ function createGlobalChat(opts) {
154
386
  effort: resolved.effort,
155
387
  fast: resolved.fast,
156
388
  planMode: Boolean(opts.planMode),
157
- attachments: opts.attachments ?? [],
389
+ attachments: persistPendingFileAttachments(
390
+ worktreePath,
391
+ opts.attachments ?? []
392
+ ),
158
393
  parentThreadId: opts.parentThreadId ?? null,
159
394
  status: "idle"
160
395
  });
@@ -276,6 +511,10 @@ function ensureCloudCoordinator(agent) {
276
511
  }
277
512
 
278
513
  export {
514
+ stageAbsolutePathsAsAttachments,
515
+ stageBuffersAsAttachments,
516
+ persistPendingFileAttachments,
517
+ attachmentsFromWorktreePaths,
279
518
  ORCHESTRATOR_AGENT_KINDS,
280
519
  isOrchestratorCapableAgent,
281
520
  assertOrchestratorCapableAgent,
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  isGlobalRepoPath
3
- } from "./chunk-XUEI4GCF.js";
3
+ } from "./chunk-GSKRGF7B.js";
4
4
  import {
5
5
  ensureGhPreferOrigin,
6
6
  resolveRepoRoot