@sideboard-ai/core 0.1.22 → 0.1.23

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.
@@ -11,7 +11,7 @@ import {
11
11
  listBrightsyChatTargets,
12
12
  opencodeAdapter,
13
13
  permissionMode
14
- } from "./chunk-V54GKKCI.js";
14
+ } from "./chunk-WK6AK7NK.js";
15
15
  import "./chunk-ILQK4P5R.js";
16
16
  import {
17
17
  cursorSdkMessageToEvents,
@@ -25,7 +25,7 @@ import {
25
25
  allAdapters,
26
26
  getAdapter,
27
27
  parseBrightsyCliLine
28
- } from "./chunk-V54GKKCI.js";
28
+ } from "./chunk-WK6AK7NK.js";
29
29
  import {
30
30
  childEnvWithAppSettings,
31
31
  getLinearApiKey,
@@ -248,6 +248,18 @@ function toolDescription(name, input) {
248
248
  if (/connectedAgentRequest/i.test(name)) {
249
249
  return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
250
250
  }
251
+ if (/present_artifact$/i.test(name)) {
252
+ return str(input?.title) ? `Present ${str(input?.title)}` : "Present artifact";
253
+ }
254
+ if (/present_schema$/i.test(name)) {
255
+ return str(input?.title) ? `Schema ${str(input?.title)}` : "Present schema";
256
+ }
257
+ if (/present_files$/i.test(name)) {
258
+ return str(input?.title) ? `Files ${str(input?.title)}` : "Present files";
259
+ }
260
+ if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
261
+ return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
262
+ }
251
263
  if (!input) return n;
252
264
  if (/bash|shell|terminal/i.test(name) && str(input.command)) {
253
265
  const cmd = str(input.command);
@@ -606,6 +618,26 @@ function formatWorktreeDirective(thread, opts) {
606
618
  }
607
619
  return lines.join("\n");
608
620
  }
621
+ function formatArtifactDirective() {
622
+ return [
623
+ "Sideboard side column (desktop UI):",
624
+ "claude.ai\u2019s \u201CArtifact\u201D tool does NOT exist in Claude Code. That is expected.",
625
+ "Documents (HTML/SVG/markdown):",
626
+ "1) Emit a fenced code block tagged `html` (preferred), `svg`, or `markdown` with the FULL document \u2014 Sideboard opens a side column. Example:",
627
+ "```html",
628
+ "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
629
+ "```",
630
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content.",
631
+ "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
632
+ "3) Call Sideboard MCP `present_schema` with title, mode (table|form), and either:",
633
+ " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
634
+ " - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
635
+ "Files / media browser (CMS file manager column):",
636
+ "4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
637
+ " Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
638
+ "Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages."
639
+ ].join("\n");
640
+ }
609
641
  var FILES_BY_AGENT = {
610
642
  claude: [
611
643
  "CLAUDE.md",
@@ -1473,6 +1505,27 @@ function isImageRelativePath(relativePath) {
1473
1505
  const ext = base.includes(".") ? base.split(".").pop() || "" : "";
1474
1506
  return IMAGE_EXTENSIONS.has(ext);
1475
1507
  }
1508
+ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
1509
+ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
1510
+ assertSafeRelativePath(relativePath);
1511
+ const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
1512
+ const abs = join4(worktreePath, relativePath);
1513
+ const st = statSync2(abs);
1514
+ if (!st.isFile()) {
1515
+ throw new Error(`Not a file: ${relativePath}`);
1516
+ }
1517
+ if (st.size > maxBytes) {
1518
+ throw new Error(
1519
+ `File too large to upload (${st.size} bytes; max ${maxBytes})`
1520
+ );
1521
+ }
1522
+ const buf = readFileSync4(abs);
1523
+ return {
1524
+ path: relativePath,
1525
+ contentBase64: buf.toString("base64"),
1526
+ size: buf.length
1527
+ };
1528
+ }
1476
1529
  function readWorktreeFile(worktreePath, relativePath, opts) {
1477
1530
  assertSafeRelativePath(relativePath);
1478
1531
  const maxBytes = opts?.maxBytes ?? 2e5;
@@ -2273,7 +2326,7 @@ async function createThread(input, onSetupLine) {
2273
2326
  return readThread(thread.id) ?? thread;
2274
2327
  }
2275
2328
  async function listLinearIssues(agent, repoPath) {
2276
- const { getAdapter: getAdapter2 } = await import("./agents-RYOW25YJ.js");
2329
+ const { getAdapter: getAdapter2 } = await import("./agents-LJJRPW4Y.js");
2277
2330
  await requireAgent(agent, { requireLinear: true });
2278
2331
  const adapter = getAdapter2(agent);
2279
2332
  if (!adapter.listLinearIssues) {
@@ -3189,9 +3242,18 @@ var Orchestrator = class {
3189
3242
  parentId: threadId,
3190
3243
  goal: thread.sourceRef || thread.title
3191
3244
  }) : null;
3245
+ const artifactReminder = thread.agent !== "brightsy" ? [
3246
+ "Sideboard side column (important):",
3247
+ "There is no claude.ai Artifact tool here \u2014 that is normal.",
3248
+ "HTML/SVG/markdown: ```html fence or MCP present_artifact.",
3249
+ "CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
3250
+ "Files column: MCP present_files (brightsy account storage or memory).",
3251
+ "Do not say artifacts/CMS UI are unavailable."
3252
+ ].join(" ") : null;
3192
3253
  const agentPrompt = [
3193
3254
  thread.planMode ? PLAN_MODE_INSTRUCTION : null,
3194
3255
  orchestrationReminder,
3256
+ artifactReminder,
3195
3257
  expandedPrompt
3196
3258
  ].filter(Boolean).join("\n\n");
3197
3259
  const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
@@ -3216,6 +3278,7 @@ var Orchestrator = class {
3216
3278
  () => null
3217
3279
  )
3218
3280
  });
3281
+ const artifactDirective = isBrightsy ? null : formatArtifactDirective();
3219
3282
  const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
3220
3283
  const { autoRenameBranchEnabled } = await import("./app-settings-BDMLWCWI.js");
3221
3284
  const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled() ? formatRenameBranchDirective(fresh, {
@@ -3243,6 +3306,7 @@ var Orchestrator = class {
3243
3306
  const cachedPrefix = [
3244
3307
  coordinatorDirective,
3245
3308
  worktreeDirective,
3309
+ artifactDirective,
3246
3310
  renameBranchDirective,
3247
3311
  ...fresh.agent === "claude" && fresh.sessionId ? [] : [instructions, seed]
3248
3312
  ].filter(Boolean).join("\n\n---\n\n");
@@ -3663,6 +3727,13 @@ var Orchestrator = class {
3663
3727
  }
3664
3728
  return readWorktreeFile(thread.worktreePath, relativePath);
3665
3729
  }
3730
+ async readFileForUpload(threadRef, relativePath) {
3731
+ const thread = this.requireThread(threadRef);
3732
+ if (relativePath.includes("..") || relativePath.startsWith("/")) {
3733
+ throw new Error("Invalid path");
3734
+ }
3735
+ return readWorktreeFileForUpload(thread.worktreePath, relativePath);
3736
+ }
3666
3737
  async writeFile(threadRef, relativePath, content) {
3667
3738
  const thread = this.requireThread(threadRef);
3668
3739
  if (relativePath.includes("..") || relativePath.startsWith("/")) {
@@ -4038,6 +4109,82 @@ async function startMcpServer() {
4038
4109
  return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
4039
4110
  }
4040
4111
  );
4112
+ server.tool(
4113
+ "present_artifact",
4114
+ "Show an HTML, SVG, or markdown document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Prefer type=html for interactive pages.",
4115
+ {
4116
+ title: z.string().describe("Short title shown in the artifact pane header"),
4117
+ type: z.enum(["html", "svg", "markdown"]).describe("Artifact kind \u2014 html opens an iframe preview"),
4118
+ content: z.string().describe("Full document body (complete HTML page, SVG markup, or markdown)"),
4119
+ artifact_id: z.string().optional().describe("Stable id when updating the same artifact across turns")
4120
+ },
4121
+ async ({ title, type, content, artifact_id }) => {
4122
+ const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
4123
+ const payload = {
4124
+ ok: true,
4125
+ artifact_id: id,
4126
+ title,
4127
+ type,
4128
+ content,
4129
+ message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
4130
+ };
4131
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
4132
+ }
4133
+ );
4134
+ server.tool(
4135
+ "present_schema",
4136
+ "Open Sideboard\u2019s schema-driven CMS side column (filterable table and/or form). Pass JSON Schema + schemaUi (Brightsy extensions supported). Use datasource=brightsy with resource_id (record type UUID) when logged into Brightsy; use datasource=inline with embedded resource/records for any other source.",
4137
+ {
4138
+ title: z.string().describe("Pane title"),
4139
+ mode: z.enum(["table", "form"]).optional().describe("table = list/filter records; form = edit one record"),
4140
+ datasource: z.enum(["brightsy", "inline"]).optional().describe("brightsy resolves via login; inline uses embedded resource/records"),
4141
+ resource_id: z.string().optional().describe("Brightsy record type UUID (or generic resource id)"),
4142
+ record_id: z.string().optional().describe("Record id when opening form mode"),
4143
+ resource: z.record(z.unknown()).optional().describe("Inline { id, title, schema, schemaUi?, slug? }"),
4144
+ record: z.record(z.unknown()).optional().describe("Inline record { id, data, published_at? }"),
4145
+ records: z.array(z.record(z.unknown())).optional().describe("Inline records for table mode"),
4146
+ pane_id: z.string().optional().describe("Stable pane id across updates")
4147
+ },
4148
+ async (args) => {
4149
+ const id = args.pane_id?.trim() || `schema_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
4150
+ const payload = {
4151
+ ok: true,
4152
+ pane_id: id,
4153
+ title: args.title,
4154
+ mode: args.mode ?? (args.record_id || args.record ? "form" : "table"),
4155
+ datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
4156
+ resource_id: args.resource_id,
4157
+ record_id: args.record_id,
4158
+ resource: args.resource,
4159
+ record: args.record,
4160
+ records: args.records,
4161
+ message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
4162
+ };
4163
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
4164
+ }
4165
+ );
4166
+ server.tool(
4167
+ "present_files",
4168
+ "Open Sideboard\u2019s Files column (CMS-style file manager: browse, upload, pick). Use datasource=brightsy when the user is logged into Brightsy account storage; datasource=memory for a session-local demo store. Prefer this over claiming a file manager UI is unavailable. Pair with present_schema when editing records that need media.",
4169
+ {
4170
+ title: z.string().optional().describe("Pane title (default: Files)"),
4171
+ datasource: z.enum(["brightsy", "memory"]).optional().describe("brightsy = account storage via login; memory = session demo store"),
4172
+ path: z.string().optional().describe("Initial folder path (e.g. public)"),
4173
+ pane_id: z.string().optional().describe("Stable pane id across updates")
4174
+ },
4175
+ async (args) => {
4176
+ const id = args.pane_id?.trim() || `files_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
4177
+ const payload = {
4178
+ ok: true,
4179
+ pane_id: id,
4180
+ title: args.title?.trim() || "Files",
4181
+ datasource: args.datasource ?? "brightsy",
4182
+ path: args.path,
4183
+ message: "Files pane accepted. Sideboard desktop opens the Files column beside chat."
4184
+ };
4185
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
4186
+ }
4187
+ );
4041
4188
  server.tool(
4042
4189
  "create_thread",
4043
4190
  "Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces and parentThreadId when spawning from an orchestrator. Then use send_to_thread to chat.",
@@ -4465,6 +4612,7 @@ export {
4465
4612
  spawnAgentTurn,
4466
4613
  formatRenameBranchDirective,
4467
4614
  formatWorktreeDirective,
4615
+ formatArtifactDirective,
4468
4616
  loadAgentInstructions,
4469
4617
  formatAgentInstructions,
4470
4618
  withAgentInstructions,
@@ -4492,6 +4640,7 @@ export {
4492
4640
  listBranchCommits,
4493
4641
  getDiff,
4494
4642
  listWorktreeFiles,
4643
+ readWorktreeFileForUpload,
4495
4644
  readWorktreeFile,
4496
4645
  writeWorktreeFile,
4497
4646
  getDiffSummary,
@@ -428,6 +428,11 @@ var SIDEBOARD_MCP_ALLOWED_TOOLS = [
428
428
  "mcp__sideboard",
429
429
  "mcp__sideboard__*"
430
430
  ];
431
+ var SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
432
+ "mcp__sideboard__present_artifact",
433
+ "mcp__sideboard__present_schema",
434
+ "mcp__sideboard__present_files"
435
+ ];
431
436
  var BRIGHTSY_MCP_ALLOWED_TOOLS = [
432
437
  "mcp__brightsy",
433
438
  "mcp__brightsy__*"
@@ -518,10 +523,6 @@ function findSideboardMcpJsEntry() {
518
523
  return null;
519
524
  }
520
525
  async function resolveSideboardMcpServer() {
521
- const which = await run("which", ["sideboard"], { reject: false });
522
- if (which.exitCode === 0 && which.stdout.trim()) {
523
- return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
524
- }
525
526
  const entry = findSideboardMcpJsEntry();
526
527
  if (entry) {
527
528
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
@@ -532,6 +533,10 @@ async function resolveSideboardMcpServer() {
532
533
  args: isCli ? [entry, "mcp"] : [entry]
533
534
  };
534
535
  }
536
+ const which = await run("which", ["sideboard"], { reject: false });
537
+ if (which.exitCode === 0 && which.stdout.trim()) {
538
+ return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
539
+ }
535
540
  return { name: "sideboard", command: "sideboard", args: ["mcp"] };
536
541
  }
537
542
  async function buildInjectedMcpServers(opts) {
@@ -736,7 +741,7 @@ var claudeAdapter = {
736
741
  const { isOrchestratorThread } = await import("./global-workspace-LM4AA4RO.js");
737
742
  const isOrchestrator = isOrchestratorThread(thread);
738
743
  const injectedServers = await buildInjectedMcpServers({
739
- includeSideboard: isOrchestrator,
744
+ includeSideboard: true,
740
745
  includeBrightsy: isBrightsyConnected()
741
746
  });
742
747
  const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
@@ -753,6 +758,7 @@ var claudeAdapter = {
753
758
  allowedTools = [
754
759
  ...BASE_ALLOWED_TOOLS,
755
760
  ...mcpAllowTools(servers),
761
+ ...SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS,
756
762
  ...brightsyMcpAllowedTools(injectedBrightsyNames)
757
763
  ];
758
764
  }
package/dist/index.cjs CHANGED
@@ -4084,10 +4084,6 @@ function findSideboardMcpJsEntry() {
4084
4084
  return null;
4085
4085
  }
4086
4086
  async function resolveSideboardMcpServer() {
4087
- const which = await run("which", ["sideboard"], { reject: false });
4088
- if (which.exitCode === 0 && which.stdout.trim()) {
4089
- return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
4090
- }
4091
4087
  const entry = findSideboardMcpJsEntry();
4092
4088
  if (entry) {
4093
4089
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
@@ -4098,6 +4094,10 @@ async function resolveSideboardMcpServer() {
4098
4094
  args: isCli ? [entry, "mcp"] : [entry]
4099
4095
  };
4100
4096
  }
4097
+ const which = await run("which", ["sideboard"], { reject: false });
4098
+ if (which.exitCode === 0 && which.stdout.trim()) {
4099
+ return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
4100
+ }
4101
4101
  return { name: "sideboard", command: "sideboard", args: ["mcp"] };
4102
4102
  }
4103
4103
  async function buildInjectedMcpServers(opts) {
@@ -4140,7 +4140,7 @@ function writeMcpServersConfig(servers) {
4140
4140
  async function writeInjectedMcpConfig(opts) {
4141
4141
  return writeMcpServersConfig(await buildInjectedMcpServers(opts));
4142
4142
  }
4143
- var import_node_fs10, import_node_module, import_node_os6, import_node_path11, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache;
4143
+ var import_node_fs10, import_node_module, import_node_os6, import_node_path11, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, BRIGHTSY_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache;
4144
4144
  var init_injected_mcp = __esm({
4145
4145
  "src/agents/injected-mcp.ts"() {
4146
4146
  "use strict";
@@ -4157,6 +4157,11 @@ var init_injected_mcp = __esm({
4157
4157
  "mcp__sideboard",
4158
4158
  "mcp__sideboard__*"
4159
4159
  ];
4160
+ SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
4161
+ "mcp__sideboard__present_artifact",
4162
+ "mcp__sideboard__present_schema",
4163
+ "mcp__sideboard__present_files"
4164
+ ];
4160
4165
  BRIGHTSY_MCP_ALLOWED_TOOLS = [
4161
4166
  "mcp__brightsy",
4162
4167
  "mcp__brightsy__*"
@@ -4368,7 +4373,7 @@ var init_claude = __esm({
4368
4373
  const { isOrchestratorThread: isOrchestratorThread2 } = await Promise.resolve().then(() => (init_global_workspace(), global_workspace_exports));
4369
4374
  const isOrchestrator = isOrchestratorThread2(thread);
4370
4375
  const injectedServers = await buildInjectedMcpServers({
4371
- includeSideboard: isOrchestrator,
4376
+ includeSideboard: true,
4372
4377
  includeBrightsy: isBrightsyConnected()
4373
4378
  });
4374
4379
  const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
@@ -4385,6 +4390,7 @@ var init_claude = __esm({
4385
4390
  allowedTools = [
4386
4391
  ...BASE_ALLOWED_TOOLS,
4387
4392
  ...mcpAllowTools(servers),
4393
+ ...SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS,
4388
4394
  ...brightsyMcpAllowedTools(injectedBrightsyNames)
4389
4395
  ];
4390
4396
  }
@@ -5309,6 +5315,7 @@ __export(index_exports, {
5309
5315
  forkMessageSlice: () => forkMessageSlice,
5310
5316
  forkThreadWorktree: () => forkThreadWorktree,
5311
5317
  formatAgentInstructions: () => formatAgentInstructions,
5318
+ formatArtifactDirective: () => formatArtifactDirective,
5312
5319
  formatBrightsyFetchError: () => formatBrightsyFetchError,
5313
5320
  formatGhLandError: () => formatGhLandError,
5314
5321
  formatIpcInvokeError: () => formatIpcInvokeError,
@@ -5409,6 +5416,7 @@ __export(index_exports, {
5409
5416
  readSkillBody: () => readSkillBody,
5410
5417
  readThread: () => readThread,
5411
5418
  readWorktreeFile: () => readWorktreeFile,
5419
+ readWorktreeFileForUpload: () => readWorktreeFileForUpload,
5412
5420
  readWorktreeInclude: () => readWorktreeInclude,
5413
5421
  refreshGitHubAuth: () => refreshGitHubAuth,
5414
5422
  removeWorkspace: () => removeWorkspace,
@@ -5712,6 +5720,18 @@ function toolDescription(name, input) {
5712
5720
  if (/connectedAgentRequest/i.test(name)) {
5713
5721
  return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
5714
5722
  }
5723
+ if (/present_artifact$/i.test(name)) {
5724
+ return str(input?.title) ? `Present ${str(input?.title)}` : "Present artifact";
5725
+ }
5726
+ if (/present_schema$/i.test(name)) {
5727
+ return str(input?.title) ? `Schema ${str(input?.title)}` : "Present schema";
5728
+ }
5729
+ if (/present_files$/i.test(name)) {
5730
+ return str(input?.title) ? `Files ${str(input?.title)}` : "Present files";
5731
+ }
5732
+ if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
5733
+ return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
5734
+ }
5715
5735
  if (!input) return n;
5716
5736
  if (/bash|shell|terminal/i.test(name) && str(input.command)) {
5717
5737
  const cmd = str(input.command);
@@ -6075,6 +6095,26 @@ function formatWorktreeDirective(thread, opts) {
6075
6095
  }
6076
6096
  return lines.join("\n");
6077
6097
  }
6098
+ function formatArtifactDirective() {
6099
+ return [
6100
+ "Sideboard side column (desktop UI):",
6101
+ "claude.ai\u2019s \u201CArtifact\u201D tool does NOT exist in Claude Code. That is expected.",
6102
+ "Documents (HTML/SVG/markdown):",
6103
+ "1) Emit a fenced code block tagged `html` (preferred), `svg`, or `markdown` with the FULL document \u2014 Sideboard opens a side column. Example:",
6104
+ "```html",
6105
+ "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
6106
+ "```",
6107
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content.",
6108
+ "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
6109
+ "3) Call Sideboard MCP `present_schema` with title, mode (table|form), and either:",
6110
+ " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
6111
+ " - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
6112
+ "Files / media browser (CMS file manager column):",
6113
+ "4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
6114
+ " Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
6115
+ "Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages."
6116
+ ].join("\n");
6117
+ }
6078
6118
  var FILES_BY_AGENT = {
6079
6119
  claude: [
6080
6120
  "CLAUDE.md",
@@ -6946,6 +6986,27 @@ function isImageRelativePath(relativePath) {
6946
6986
  const ext = base.includes(".") ? base.split(".").pop() || "" : "";
6947
6987
  return IMAGE_EXTENSIONS.has(ext);
6948
6988
  }
6989
+ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
6990
+ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
6991
+ assertSafeRelativePath(relativePath);
6992
+ const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
6993
+ const abs = (0, import_node_path17.join)(worktreePath, relativePath);
6994
+ const st = (0, import_node_fs17.statSync)(abs);
6995
+ if (!st.isFile()) {
6996
+ throw new Error(`Not a file: ${relativePath}`);
6997
+ }
6998
+ if (st.size > maxBytes) {
6999
+ throw new Error(
7000
+ `File too large to upload (${st.size} bytes; max ${maxBytes})`
7001
+ );
7002
+ }
7003
+ const buf = (0, import_node_fs17.readFileSync)(abs);
7004
+ return {
7005
+ path: relativePath,
7006
+ contentBase64: buf.toString("base64"),
7007
+ size: buf.length
7008
+ };
7009
+ }
6949
7010
  function readWorktreeFile(worktreePath, relativePath, opts) {
6950
7011
  assertSafeRelativePath(relativePath);
6951
7012
  const maxBytes = opts?.maxBytes ?? 2e5;
@@ -8741,9 +8802,18 @@ var Orchestrator = class {
8741
8802
  parentId: threadId,
8742
8803
  goal: thread.sourceRef || thread.title
8743
8804
  }) : null;
8805
+ const artifactReminder = thread.agent !== "brightsy" ? [
8806
+ "Sideboard side column (important):",
8807
+ "There is no claude.ai Artifact tool here \u2014 that is normal.",
8808
+ "HTML/SVG/markdown: ```html fence or MCP present_artifact.",
8809
+ "CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
8810
+ "Files column: MCP present_files (brightsy account storage or memory).",
8811
+ "Do not say artifacts/CMS UI are unavailable."
8812
+ ].join(" ") : null;
8744
8813
  const agentPrompt = [
8745
8814
  thread.planMode ? PLAN_MODE_INSTRUCTION : null,
8746
8815
  orchestrationReminder,
8816
+ artifactReminder,
8747
8817
  expandedPrompt
8748
8818
  ].filter(Boolean).join("\n\n");
8749
8819
  const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
@@ -8768,6 +8838,7 @@ var Orchestrator = class {
8768
8838
  () => null
8769
8839
  )
8770
8840
  });
8841
+ const artifactDirective = isBrightsy ? null : formatArtifactDirective();
8771
8842
  const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
8772
8843
  const { autoRenameBranchEnabled: autoRenameBranchEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
8773
8844
  const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
@@ -8795,6 +8866,7 @@ var Orchestrator = class {
8795
8866
  const cachedPrefix = [
8796
8867
  coordinatorDirective,
8797
8868
  worktreeDirective,
8869
+ artifactDirective,
8798
8870
  renameBranchDirective,
8799
8871
  ...fresh.agent === "claude" && fresh.sessionId ? [] : [instructions, seed]
8800
8872
  ].filter(Boolean).join("\n\n---\n\n");
@@ -9215,6 +9287,13 @@ var Orchestrator = class {
9215
9287
  }
9216
9288
  return readWorktreeFile(thread.worktreePath, relativePath);
9217
9289
  }
9290
+ async readFileForUpload(threadRef, relativePath) {
9291
+ const thread = this.requireThread(threadRef);
9292
+ if (relativePath.includes("..") || relativePath.startsWith("/")) {
9293
+ throw new Error("Invalid path");
9294
+ }
9295
+ return readWorktreeFileForUpload(thread.worktreePath, relativePath);
9296
+ }
9218
9297
  async writeFile(threadRef, relativePath, content) {
9219
9298
  const thread = this.requireThread(threadRef);
9220
9299
  if (relativePath.includes("..") || relativePath.startsWith("/")) {
@@ -9596,6 +9675,82 @@ async function startMcpServer() {
9596
9675
  return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
9597
9676
  }
9598
9677
  );
9678
+ server.tool(
9679
+ "present_artifact",
9680
+ "Show an HTML, SVG, or markdown document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Prefer type=html for interactive pages.",
9681
+ {
9682
+ title: import_zod.z.string().describe("Short title shown in the artifact pane header"),
9683
+ type: import_zod.z.enum(["html", "svg", "markdown"]).describe("Artifact kind \u2014 html opens an iframe preview"),
9684
+ content: import_zod.z.string().describe("Full document body (complete HTML page, SVG markup, or markdown)"),
9685
+ artifact_id: import_zod.z.string().optional().describe("Stable id when updating the same artifact across turns")
9686
+ },
9687
+ async ({ title, type, content, artifact_id }) => {
9688
+ const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
9689
+ const payload = {
9690
+ ok: true,
9691
+ artifact_id: id,
9692
+ title,
9693
+ type,
9694
+ content,
9695
+ message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
9696
+ };
9697
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
9698
+ }
9699
+ );
9700
+ server.tool(
9701
+ "present_schema",
9702
+ "Open Sideboard\u2019s schema-driven CMS side column (filterable table and/or form). Pass JSON Schema + schemaUi (Brightsy extensions supported). Use datasource=brightsy with resource_id (record type UUID) when logged into Brightsy; use datasource=inline with embedded resource/records for any other source.",
9703
+ {
9704
+ title: import_zod.z.string().describe("Pane title"),
9705
+ mode: import_zod.z.enum(["table", "form"]).optional().describe("table = list/filter records; form = edit one record"),
9706
+ datasource: import_zod.z.enum(["brightsy", "inline"]).optional().describe("brightsy resolves via login; inline uses embedded resource/records"),
9707
+ resource_id: import_zod.z.string().optional().describe("Brightsy record type UUID (or generic resource id)"),
9708
+ record_id: import_zod.z.string().optional().describe("Record id when opening form mode"),
9709
+ resource: import_zod.z.record(import_zod.z.unknown()).optional().describe("Inline { id, title, schema, schemaUi?, slug? }"),
9710
+ record: import_zod.z.record(import_zod.z.unknown()).optional().describe("Inline record { id, data, published_at? }"),
9711
+ records: import_zod.z.array(import_zod.z.record(import_zod.z.unknown())).optional().describe("Inline records for table mode"),
9712
+ pane_id: import_zod.z.string().optional().describe("Stable pane id across updates")
9713
+ },
9714
+ async (args) => {
9715
+ const id = args.pane_id?.trim() || `schema_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
9716
+ const payload = {
9717
+ ok: true,
9718
+ pane_id: id,
9719
+ title: args.title,
9720
+ mode: args.mode ?? (args.record_id || args.record ? "form" : "table"),
9721
+ datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
9722
+ resource_id: args.resource_id,
9723
+ record_id: args.record_id,
9724
+ resource: args.resource,
9725
+ record: args.record,
9726
+ records: args.records,
9727
+ message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
9728
+ };
9729
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
9730
+ }
9731
+ );
9732
+ server.tool(
9733
+ "present_files",
9734
+ "Open Sideboard\u2019s Files column (CMS-style file manager: browse, upload, pick). Use datasource=brightsy when the user is logged into Brightsy account storage; datasource=memory for a session-local demo store. Prefer this over claiming a file manager UI is unavailable. Pair with present_schema when editing records that need media.",
9735
+ {
9736
+ title: import_zod.z.string().optional().describe("Pane title (default: Files)"),
9737
+ datasource: import_zod.z.enum(["brightsy", "memory"]).optional().describe("brightsy = account storage via login; memory = session demo store"),
9738
+ path: import_zod.z.string().optional().describe("Initial folder path (e.g. public)"),
9739
+ pane_id: import_zod.z.string().optional().describe("Stable pane id across updates")
9740
+ },
9741
+ async (args) => {
9742
+ const id = args.pane_id?.trim() || `files_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
9743
+ const payload = {
9744
+ ok: true,
9745
+ pane_id: id,
9746
+ title: args.title?.trim() || "Files",
9747
+ datasource: args.datasource ?? "brightsy",
9748
+ path: args.path,
9749
+ message: "Files pane accepted. Sideboard desktop opens the Files column beside chat."
9750
+ };
9751
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
9752
+ }
9753
+ );
9599
9754
  server.tool(
9600
9755
  "create_thread",
9601
9756
  "Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces and parentThreadId when spawning from an orchestrator. Then use send_to_thread to chat.",
@@ -10454,6 +10609,7 @@ init_injected_mcp();
10454
10609
  forkMessageSlice,
10455
10610
  forkThreadWorktree,
10456
10611
  formatAgentInstructions,
10612
+ formatArtifactDirective,
10457
10613
  formatBrightsyFetchError,
10458
10614
  formatGhLandError,
10459
10615
  formatIpcInvokeError,
@@ -10554,6 +10710,7 @@ init_injected_mcp();
10554
10710
  readSkillBody,
10555
10711
  readThread,
10556
10712
  readWorktreeFile,
10713
+ readWorktreeFileForUpload,
10557
10714
  readWorktreeInclude,
10558
10715
  refreshGitHubAuth,
10559
10716
  removeWorkspace,
package/dist/index.d.cts CHANGED
@@ -1212,6 +1212,11 @@ declare function formatRenameBranchDirective(thread: Pick<Thread, 'worktreePath'
1212
1212
  declare function formatWorktreeDirective(thread: Pick<Thread, 'worktreePath' | 'repoPath' | 'branchName'> & Partial<Pick<Thread, 'title' | 'prUrl'>>, opts?: {
1213
1213
  githubSlug?: string | null;
1214
1214
  }): string;
1215
+ /**
1216
+ * Tell agents how Sideboard renders Claude-style artifacts (side column).
1217
+ * Claude Code has no claude.ai `artifact` tool — fences / present_artifact instead.
1218
+ */
1219
+ declare function formatArtifactDirective(): string;
1215
1220
  interface AgentInstructionFile {
1216
1221
  relativePath: string;
1217
1222
  content: string;
@@ -1417,6 +1422,17 @@ declare function getDiff(worktreePath: string, repoPath: string, opts?: GetDiffO
1417
1422
  declare function listWorktreeFiles(worktreePath: string, opts?: {
1418
1423
  maxFiles?: number;
1419
1424
  }): Promise<string[]>;
1425
+ /**
1426
+ * Read a worktree file as base64 for upload (any type, not the editor stub).
1427
+ * Rejects files larger than maxBytes.
1428
+ */
1429
+ declare function readWorktreeFileForUpload(worktreePath: string, relativePath: string, opts?: {
1430
+ maxBytes?: number;
1431
+ }): {
1432
+ path: string;
1433
+ contentBase64: string;
1434
+ size: number;
1435
+ };
1420
1436
  /** Read a text (or image) file from the worktree (capped). */
1421
1437
  declare function readWorktreeFile(worktreePath: string, relativePath: string, opts?: {
1422
1438
  maxBytes?: number;
@@ -1772,6 +1788,11 @@ declare class Orchestrator {
1772
1788
  binary: boolean;
1773
1789
  encoding: 'utf8' | 'base64';
1774
1790
  }>;
1791
+ readFileForUpload(threadRef: string, relativePath: string): Promise<{
1792
+ path: string;
1793
+ contentBase64: string;
1794
+ size: number;
1795
+ }>;
1775
1796
  writeFile(threadRef: string, relativePath: string, content: string): Promise<{
1776
1797
  path: string;
1777
1798
  }>;
@@ -1958,6 +1979,17 @@ interface IpcApi {
1958
1979
  listBrightsyChatTargets(): Promise<BrightsyChatTargets>;
1959
1980
  /** Brightsy login + connected teams (shared by CLI, Brightsy agent, and Claude MCP). */
1960
1981
  getBrightsySession(): Promise<BrightsySession>;
1982
+ /**
1983
+ * Auth for schema CMS pane (`@brightsy/client` in the renderer).
1984
+ * Returns null fields + reason when not logged in.
1985
+ */
1986
+ getBrightsyCmsAuth(): Promise<{
1987
+ endpoint: string;
1988
+ accessToken: string | null;
1989
+ accountId: string | null;
1990
+ accountSlug: string | null;
1991
+ reason?: string;
1992
+ }>;
1961
1993
  /** Connect/activate a team for CLI + MCP (same as connectBrightsyTeam). */
1962
1994
  switchBrightsyAccount(accountIdOrSlug: string): Promise<BrightsySession>;
1963
1995
  /** Connect a team for CLI + MCP; activates it as the CLI session. */
@@ -2056,6 +2088,12 @@ interface IpcApi {
2056
2088
  binary: boolean;
2057
2089
  encoding: 'utf8' | 'base64';
2058
2090
  }>;
2091
+ /** Full file bytes (base64) for CMS / file-manager upload from worktree paths. */
2092
+ readFileForUpload(threadRef: string, relativePath: string): Promise<{
2093
+ path: string;
2094
+ contentBase64: string;
2095
+ size: number;
2096
+ }>;
2059
2097
  writeFile(threadRef: string, relativePath: string, content: string): Promise<{
2060
2098
  path: string;
2061
2099
  }>;
@@ -2191,6 +2229,14 @@ interface IpcApi {
2191
2229
  exitCode: number | null;
2192
2230
  }>;
2193
2231
  openExternal(url: string): Promise<void>;
2232
+ /**
2233
+ * Publish HTML for the artifact side-column iframe (custom protocol bypasses
2234
+ * renderer CSP so inline scripts can run).
2235
+ */
2236
+ publishArtifactPreview(id: string, html: string): Promise<{
2237
+ url: string;
2238
+ }>;
2239
+ clearArtifactPreview(id: string): Promise<void>;
2194
2240
  /**
2195
2241
  * In-app URL preview via BrowserView (top-level navigation — works for
2196
2242
  * sites that block iframes, e.g. GitHub).
@@ -2370,7 +2416,7 @@ declare function disconnectBrightsyTeam(accountIdOrSlug: string): Promise<Connec
2370
2416
  /** Sanitize slug for Claude MCP server / tool name segments. */
2371
2417
  declare function brightsyMcpServerName(slug: string): string;
2372
2418
 
2373
- /** Claude --allowedTools entries for Sideboard MCP. */
2419
+ /** Claude --allowedTools entries for Sideboard MCP (full fleet). */
2374
2420
  declare const SIDEBOARD_MCP_ALLOWED_TOOLS: readonly ["mcp__sideboard", "mcp__sideboard__*"];
2375
2421
  /** Legacy single-server allow list (CLI ~/.brightsy fallback). */
2376
2422
  declare const BRIGHTSY_MCP_ALLOWED_TOOLS: readonly ["mcp__brightsy", "mcp__brightsy__*"];
@@ -2387,4 +2433,4 @@ declare function writeInjectedMcpConfig(opts: {
2387
2433
  includeBrightsy?: boolean;
2388
2434
  }): Promise<string | null>;
2389
2435
 
2390
- export { type ActiveRun, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentInstructionFile, type AgentKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLOUD_COORDINATOR_BUSY_REPLY, CLOUD_COORDINATOR_STOPPED_REPLY, CLOUD_COORDINATOR_TIMEOUT_REPLY, CLOUD_ORCHESTRATOR_GOAL, CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, COORDINATOR_TOOL_PLAYBOOK, type ClaudeHarnessSettings, type CleanupOrphansResult, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateThreadInput, type CreateWorktreeResult, type CursorSdkStreamMessage, type CursorTurnRequest, type CursorWorktreesConfig, type DevServerHandle, type DiffCommentInput, type DiffCommentLine, type DiffCommit, type DiffFile, type DiffResult, type DiffScope, type DiffScopeStat, type ExpandResult, FAMOUS_SOCCER_TEAMS, type ForkChatTabInput, type ForkThreadWorktreeInput, type FormatGhLandErrorOptions, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GitHubStatus, type GitWorktreeStatus, HARNESS_ENV_KEYS, type HarnessId, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, type LandPreview, type LandResult, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, Orchestrator, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PLAN_MODE_INSTRUCTION, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type RepoSettings, type RepoSetupInfo, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, type ScriptHandle, type SkillInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, type TeamName, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type TranscriptToolDetail, type TurnCommand, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, addWorkspace, adoptThread, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyThreadIntoMain, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, captureLoginEnv, captureTurnBaseline, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, collectTakenTeamSlugs, commitAll, conductorDbPath, confirmLand, connectBrightsyTeam, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createGlobalChat, createOrUpdatePr, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectLocalMergeConflicts, disconnectBrightsyTeam, discoverSkills, encodeBrightsyTarget, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractiveSummary, fetchPrHead, finalizeParts, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatBrightsyFetchError, formatGhLandError, formatIpcInvokeError, formatMessagesAsTranscript, formatRateLimitResetHint, formatRenameBranchDirective, formatTranscriptMarkdown, formatWorkspaceInventory, formatWorktreeDirective, getAdapter, getBrightsySession, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getIssueSource, getLinearApiKey, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrMeta, getRepoSetupInfo, getRunMode, getRunScript, gh, ghHeadRef, ghRepoSelectArgs, git, globalAgentCwd, harnessEnvKey, hasConductorHook, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, importConductorWorkspace, importConductorWorkspaceAsync, initializeGitRepository, inspectGitWorktree, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isLinearConnected, isOrchestratorThread, isPlaceholderBranch, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listConductorWorkspaces, listConnectedBrightsyTeams, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listPrs, listRunScripts, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergePr, mergeUsage, normalizeParseResult, normalizeThread, normalizeTurnInput, normalizeWorktreePath, opencodeAdapter, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGithubSlugFromRemoteUrl, parseMcpList, partsToAssistantText, permissionMode, previewLand, pushBranch, readSkillBody, readThread, readWorktreeFile, readWorktreeInclude, refreshGitHubAuth, removeWorkspace, removeWorktree, repoSlug, requireAgent, resolveClaudeExecutable, resolveConductorCursorAgentId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGithubRepoSlug, resolvePrSelector, resolveRepoRoot, resolveWorktreeStartPoint, run, runArchiveScript, runCloudConnect, runCursorWorktreeSetup, runSetupScript, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, setStatus, settingsSourceLabel, shouldCompactContext, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardReposDir, sideboardWorkspacesDir, slugify, spawnAgentTurn, splitForCompaction, startDevServer, startMcpServer, startOrchestration, stripBrightsyNdjsonNoise, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, threadDisplayLabel, threadFilePath, threadLockPath, threadsDir, threadsSharingWorktree, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateIntegrationsSettings, updateThread, validateLinearApiKey, withAgentInstructions, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writeThread, writeWorktreeFile };
2436
+ export { type ActiveRun, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentInstructionFile, type AgentKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLOUD_COORDINATOR_BUSY_REPLY, CLOUD_COORDINATOR_STOPPED_REPLY, CLOUD_COORDINATOR_TIMEOUT_REPLY, CLOUD_ORCHESTRATOR_GOAL, CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, COORDINATOR_TOOL_PLAYBOOK, type ClaudeHarnessSettings, type CleanupOrphansResult, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateThreadInput, type CreateWorktreeResult, type CursorSdkStreamMessage, type CursorTurnRequest, type CursorWorktreesConfig, type DevServerHandle, type DiffCommentInput, type DiffCommentLine, type DiffCommit, type DiffFile, type DiffResult, type DiffScope, type DiffScopeStat, type ExpandResult, FAMOUS_SOCCER_TEAMS, type ForkChatTabInput, type ForkThreadWorktreeInput, type FormatGhLandErrorOptions, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GitHubStatus, type GitWorktreeStatus, HARNESS_ENV_KEYS, type HarnessId, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, type LandPreview, type LandResult, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, Orchestrator, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PLAN_MODE_INSTRUCTION, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type RepoSettings, type RepoSetupInfo, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, type ScriptHandle, type SkillInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, type TeamName, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type TranscriptToolDetail, type TurnCommand, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, addWorkspace, adoptThread, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyThreadIntoMain, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, captureLoginEnv, captureTurnBaseline, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, collectTakenTeamSlugs, commitAll, conductorDbPath, confirmLand, connectBrightsyTeam, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createGlobalChat, createOrUpdatePr, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectLocalMergeConflicts, disconnectBrightsyTeam, discoverSkills, encodeBrightsyTarget, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractiveSummary, fetchPrHead, finalizeParts, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatGhLandError, formatIpcInvokeError, formatMessagesAsTranscript, formatRateLimitResetHint, formatRenameBranchDirective, formatTranscriptMarkdown, formatWorkspaceInventory, formatWorktreeDirective, getAdapter, getBrightsySession, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getIssueSource, getLinearApiKey, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrMeta, getRepoSetupInfo, getRunMode, getRunScript, gh, ghHeadRef, ghRepoSelectArgs, git, globalAgentCwd, harnessEnvKey, hasConductorHook, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, importConductorWorkspace, importConductorWorkspaceAsync, initializeGitRepository, inspectGitWorktree, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isLinearConnected, isOrchestratorThread, isPlaceholderBranch, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listConductorWorkspaces, listConnectedBrightsyTeams, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listPrs, listRunScripts, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergePr, mergeUsage, normalizeParseResult, normalizeThread, normalizeTurnInput, normalizeWorktreePath, opencodeAdapter, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGithubSlugFromRemoteUrl, parseMcpList, partsToAssistantText, permissionMode, previewLand, pushBranch, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, refreshGitHubAuth, removeWorkspace, removeWorktree, repoSlug, requireAgent, resolveClaudeExecutable, resolveConductorCursorAgentId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGithubRepoSlug, resolvePrSelector, resolveRepoRoot, resolveWorktreeStartPoint, run, runArchiveScript, runCloudConnect, runCursorWorktreeSetup, runSetupScript, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, setStatus, settingsSourceLabel, shouldCompactContext, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardReposDir, sideboardWorkspacesDir, slugify, spawnAgentTurn, splitForCompaction, startDevServer, startMcpServer, startOrchestration, stripBrightsyNdjsonNoise, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, threadDisplayLabel, threadFilePath, threadLockPath, threadsDir, threadsSharingWorktree, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateIntegrationsSettings, updateThread, validateLinearApiKey, withAgentInstructions, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writeThread, writeWorktreeFile };
package/dist/index.d.ts CHANGED
@@ -1212,6 +1212,11 @@ declare function formatRenameBranchDirective(thread: Pick<Thread, 'worktreePath'
1212
1212
  declare function formatWorktreeDirective(thread: Pick<Thread, 'worktreePath' | 'repoPath' | 'branchName'> & Partial<Pick<Thread, 'title' | 'prUrl'>>, opts?: {
1213
1213
  githubSlug?: string | null;
1214
1214
  }): string;
1215
+ /**
1216
+ * Tell agents how Sideboard renders Claude-style artifacts (side column).
1217
+ * Claude Code has no claude.ai `artifact` tool — fences / present_artifact instead.
1218
+ */
1219
+ declare function formatArtifactDirective(): string;
1215
1220
  interface AgentInstructionFile {
1216
1221
  relativePath: string;
1217
1222
  content: string;
@@ -1417,6 +1422,17 @@ declare function getDiff(worktreePath: string, repoPath: string, opts?: GetDiffO
1417
1422
  declare function listWorktreeFiles(worktreePath: string, opts?: {
1418
1423
  maxFiles?: number;
1419
1424
  }): Promise<string[]>;
1425
+ /**
1426
+ * Read a worktree file as base64 for upload (any type, not the editor stub).
1427
+ * Rejects files larger than maxBytes.
1428
+ */
1429
+ declare function readWorktreeFileForUpload(worktreePath: string, relativePath: string, opts?: {
1430
+ maxBytes?: number;
1431
+ }): {
1432
+ path: string;
1433
+ contentBase64: string;
1434
+ size: number;
1435
+ };
1420
1436
  /** Read a text (or image) file from the worktree (capped). */
1421
1437
  declare function readWorktreeFile(worktreePath: string, relativePath: string, opts?: {
1422
1438
  maxBytes?: number;
@@ -1772,6 +1788,11 @@ declare class Orchestrator {
1772
1788
  binary: boolean;
1773
1789
  encoding: 'utf8' | 'base64';
1774
1790
  }>;
1791
+ readFileForUpload(threadRef: string, relativePath: string): Promise<{
1792
+ path: string;
1793
+ contentBase64: string;
1794
+ size: number;
1795
+ }>;
1775
1796
  writeFile(threadRef: string, relativePath: string, content: string): Promise<{
1776
1797
  path: string;
1777
1798
  }>;
@@ -1958,6 +1979,17 @@ interface IpcApi {
1958
1979
  listBrightsyChatTargets(): Promise<BrightsyChatTargets>;
1959
1980
  /** Brightsy login + connected teams (shared by CLI, Brightsy agent, and Claude MCP). */
1960
1981
  getBrightsySession(): Promise<BrightsySession>;
1982
+ /**
1983
+ * Auth for schema CMS pane (`@brightsy/client` in the renderer).
1984
+ * Returns null fields + reason when not logged in.
1985
+ */
1986
+ getBrightsyCmsAuth(): Promise<{
1987
+ endpoint: string;
1988
+ accessToken: string | null;
1989
+ accountId: string | null;
1990
+ accountSlug: string | null;
1991
+ reason?: string;
1992
+ }>;
1961
1993
  /** Connect/activate a team for CLI + MCP (same as connectBrightsyTeam). */
1962
1994
  switchBrightsyAccount(accountIdOrSlug: string): Promise<BrightsySession>;
1963
1995
  /** Connect a team for CLI + MCP; activates it as the CLI session. */
@@ -2056,6 +2088,12 @@ interface IpcApi {
2056
2088
  binary: boolean;
2057
2089
  encoding: 'utf8' | 'base64';
2058
2090
  }>;
2091
+ /** Full file bytes (base64) for CMS / file-manager upload from worktree paths. */
2092
+ readFileForUpload(threadRef: string, relativePath: string): Promise<{
2093
+ path: string;
2094
+ contentBase64: string;
2095
+ size: number;
2096
+ }>;
2059
2097
  writeFile(threadRef: string, relativePath: string, content: string): Promise<{
2060
2098
  path: string;
2061
2099
  }>;
@@ -2191,6 +2229,14 @@ interface IpcApi {
2191
2229
  exitCode: number | null;
2192
2230
  }>;
2193
2231
  openExternal(url: string): Promise<void>;
2232
+ /**
2233
+ * Publish HTML for the artifact side-column iframe (custom protocol bypasses
2234
+ * renderer CSP so inline scripts can run).
2235
+ */
2236
+ publishArtifactPreview(id: string, html: string): Promise<{
2237
+ url: string;
2238
+ }>;
2239
+ clearArtifactPreview(id: string): Promise<void>;
2194
2240
  /**
2195
2241
  * In-app URL preview via BrowserView (top-level navigation — works for
2196
2242
  * sites that block iframes, e.g. GitHub).
@@ -2370,7 +2416,7 @@ declare function disconnectBrightsyTeam(accountIdOrSlug: string): Promise<Connec
2370
2416
  /** Sanitize slug for Claude MCP server / tool name segments. */
2371
2417
  declare function brightsyMcpServerName(slug: string): string;
2372
2418
 
2373
- /** Claude --allowedTools entries for Sideboard MCP. */
2419
+ /** Claude --allowedTools entries for Sideboard MCP (full fleet). */
2374
2420
  declare const SIDEBOARD_MCP_ALLOWED_TOOLS: readonly ["mcp__sideboard", "mcp__sideboard__*"];
2375
2421
  /** Legacy single-server allow list (CLI ~/.brightsy fallback). */
2376
2422
  declare const BRIGHTSY_MCP_ALLOWED_TOOLS: readonly ["mcp__brightsy", "mcp__brightsy__*"];
@@ -2387,4 +2433,4 @@ declare function writeInjectedMcpConfig(opts: {
2387
2433
  includeBrightsy?: boolean;
2388
2434
  }): Promise<string | null>;
2389
2435
 
2390
- export { type ActiveRun, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentInstructionFile, type AgentKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLOUD_COORDINATOR_BUSY_REPLY, CLOUD_COORDINATOR_STOPPED_REPLY, CLOUD_COORDINATOR_TIMEOUT_REPLY, CLOUD_ORCHESTRATOR_GOAL, CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, COORDINATOR_TOOL_PLAYBOOK, type ClaudeHarnessSettings, type CleanupOrphansResult, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateThreadInput, type CreateWorktreeResult, type CursorSdkStreamMessage, type CursorTurnRequest, type CursorWorktreesConfig, type DevServerHandle, type DiffCommentInput, type DiffCommentLine, type DiffCommit, type DiffFile, type DiffResult, type DiffScope, type DiffScopeStat, type ExpandResult, FAMOUS_SOCCER_TEAMS, type ForkChatTabInput, type ForkThreadWorktreeInput, type FormatGhLandErrorOptions, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GitHubStatus, type GitWorktreeStatus, HARNESS_ENV_KEYS, type HarnessId, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, type LandPreview, type LandResult, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, Orchestrator, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PLAN_MODE_INSTRUCTION, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type RepoSettings, type RepoSetupInfo, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, type ScriptHandle, type SkillInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, type TeamName, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type TranscriptToolDetail, type TurnCommand, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, addWorkspace, adoptThread, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyThreadIntoMain, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, captureLoginEnv, captureTurnBaseline, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, collectTakenTeamSlugs, commitAll, conductorDbPath, confirmLand, connectBrightsyTeam, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createGlobalChat, createOrUpdatePr, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectLocalMergeConflicts, disconnectBrightsyTeam, discoverSkills, encodeBrightsyTarget, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractiveSummary, fetchPrHead, finalizeParts, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatBrightsyFetchError, formatGhLandError, formatIpcInvokeError, formatMessagesAsTranscript, formatRateLimitResetHint, formatRenameBranchDirective, formatTranscriptMarkdown, formatWorkspaceInventory, formatWorktreeDirective, getAdapter, getBrightsySession, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getIssueSource, getLinearApiKey, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrMeta, getRepoSetupInfo, getRunMode, getRunScript, gh, ghHeadRef, ghRepoSelectArgs, git, globalAgentCwd, harnessEnvKey, hasConductorHook, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, importConductorWorkspace, importConductorWorkspaceAsync, initializeGitRepository, inspectGitWorktree, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isLinearConnected, isOrchestratorThread, isPlaceholderBranch, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listConductorWorkspaces, listConnectedBrightsyTeams, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listPrs, listRunScripts, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergePr, mergeUsage, normalizeParseResult, normalizeThread, normalizeTurnInput, normalizeWorktreePath, opencodeAdapter, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGithubSlugFromRemoteUrl, parseMcpList, partsToAssistantText, permissionMode, previewLand, pushBranch, readSkillBody, readThread, readWorktreeFile, readWorktreeInclude, refreshGitHubAuth, removeWorkspace, removeWorktree, repoSlug, requireAgent, resolveClaudeExecutable, resolveConductorCursorAgentId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGithubRepoSlug, resolvePrSelector, resolveRepoRoot, resolveWorktreeStartPoint, run, runArchiveScript, runCloudConnect, runCursorWorktreeSetup, runSetupScript, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, setStatus, settingsSourceLabel, shouldCompactContext, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardReposDir, sideboardWorkspacesDir, slugify, spawnAgentTurn, splitForCompaction, startDevServer, startMcpServer, startOrchestration, stripBrightsyNdjsonNoise, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, threadDisplayLabel, threadFilePath, threadLockPath, threadsDir, threadsSharingWorktree, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateIntegrationsSettings, updateThread, validateLinearApiKey, withAgentInstructions, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writeThread, writeWorktreeFile };
2436
+ export { type ActiveRun, type AdoptInput, type AdvancedAppSettings, type AgentAdapter, type AgentEvent, type AgentInstructionFile, type AgentKind, type AgentStatus, type AgentTurnInput, type AnthropicCacheControl, type AppSettings, type ApplyIntoMainResult, type AttachCommand, type Autonomy, BRIGHTSY_MCP_ALLOWED_TOOLS, type BranchInfo, type BrightsyAccount, type BrightsyChatTarget, type BrightsyChatTargets, type BrightsyCloudConnectAgent, type BrightsyHarnessSettings, type BrightsySession, BrightsySideboardApi, type BrightsyTeamTargets, CLOUD_COORDINATOR_BUSY_REPLY, CLOUD_COORDINATOR_STOPPED_REPLY, CLOUD_COORDINATOR_TIMEOUT_REPLY, CLOUD_ORCHESTRATOR_GOAL, CONTEXT_COMPACT_CHARS, CONTEXT_KEEP_RECENT_CHARS, CONTEXT_KEEP_RECENT_MESSAGES, CONTEXT_MIN_MESSAGES, COORDINATOR_TOOL_PLAYBOOK, type ClaudeHarnessSettings, type CleanupOrphansResult, type CloudConnectAgent, type CloudConnectOptions, type CloudConnectStatus, type CompactResult, type CompactThresholds, type ConductorSettings, type ConductorWorkspace, type ConnectedBrightsyTeamInfo, type CreateChatTabInput, type CreateGlobalChatOpts, type CreateThreadInput, type CreateWorktreeResult, type CursorSdkStreamMessage, type CursorTurnRequest, type CursorWorktreesConfig, type DevServerHandle, type DiffCommentInput, type DiffCommentLine, type DiffCommit, type DiffFile, type DiffResult, type DiffScope, type DiffScopeStat, type ExpandResult, FAMOUS_SOCCER_TEAMS, type ForkChatTabInput, type ForkThreadWorktreeInput, type FormatGhLandErrorOptions, GLOBAL_WORKSPACE_ID, type GetDiffOptions, type GitHubStatus, type GitWorktreeStatus, HARNESS_ENV_KEYS, type HarnessId, type IntegrationsSettings, type IpcApi, type IssueInfo, type IssueSource, type LandPreview, type LandResult, type ListIssuesResult, MAX_ANTHROPIC_CACHE_CONTROL_BLOCKS, type McpServerStatus, type MessagePart, Orchestrator, type OrchestratorEvent, type OrchestratorRuntime, type OrphanWorktree, PLAN_MODE_INSTRUCTION, type PrActor, type PrCheckRun, type PrCommentInfo, type PrCommitInfo, type PrDetails, type PrInfo, type PrMeta, type PrReviewInfo, type RepoSettings, type RepoSetupInfo, type RunMode, type RunScript, SIDEBOARD_FORCE_STOP, SIDEBOARD_MCP_ALLOWED_TOOLS, type ScriptHandle, type SkillInfo, type SourceType, type SpawnTurnHandle, type SummarizeResult, type TeamName, type Thread, type ThreadAttachment, type ThreadMessage, type ThreadOptionsPatch, type ThreadStatus, type TokenUsage, type TranscriptToolDetail, type TurnCommand, type Workspace, type WorkspaceInventoryEntry, type WorkspaceScriptEnvOpts, addWorkspace, adoptThread, allAdapters, allocatePort, allocatePortRange, allocateTeamName, allocateTeamSlug, appDataDir, appSettingsPath, appendMessage, applyAgentEvent, applyAppEnvironment, applyCompaction, applyThreadIntoMain, autoCleanupOrphansEnabled, autoRenameBranchEnabled, autoRunAfterSetupEnabled, branchDisplayLabel, brightsyAdapter, brightsyCloudConnectAgent, brightsyCloudConnectEnabled, brightsyConfigPath, brightsyMcpAllowedTools, brightsyMcpServerName, buildCachedUserContent, buildClaudeStreamJsonUserMessage, buildDiffCommentAttachment, buildForkTranscriptAttachment, buildSessionSeed, buildWorkspaceScriptEnv, caffeinateWhileCloudConnectEnabled, caffeinateWhileRunningEnabled, captureLoginEnv, captureTurnBaseline, childEnvWithAppSettings, claudeAdapter, claudeChromeEnabled, claudeUserSettingsPath, cleanupOrphanWorktrees, cloneRepoIntoSideboard, codexAdapter, collectTakenTeamSlugs, commitAll, conductorDbPath, confirmLand, connectBrightsyTeam, coordinatorSystemPrompt, coordinatorTurnReminder, copyConfiguredFiles, countCacheControlBlocks, createChatTab, createEmptyThread, createGlobalChat, createOrUpdatePr, createThread, createThreadWorktree, currentBranch, cursorAdapter, cursorSdkMessageToEvents, decodeBrightsyTarget, deleteBranchOnPurgeEnabled, deleteThreadRecord, detectAgents, detectLocalMergeConflicts, disconnectBrightsyTeam, discoverSkills, encodeBrightsyTarget, enrichWorkspacesWithGithub, ensureAgentPath, ensureCloudCoordinator, ensureGhPreferOrigin, ensureGlobalCoordinatorCwd, ensureWorkspace, estimateMessageChars, estimateThreadChars, expandComposerPrompt, extractGhErrorDetail, extractiveSummary, fetchPrHead, finalizeParts, findInvalidCacheControlTtlOrder, findOrphanWorktrees, findThreadByRef, flattenTurnInput, forkChatTab, forkMessageSlice, forkThreadWorktree, formatAgentInstructions, formatArtifactDirective, formatBrightsyFetchError, formatGhLandError, formatIpcInvokeError, formatMessagesAsTranscript, formatRateLimitResetHint, formatRenameBranchDirective, formatTranscriptMarkdown, formatWorkspaceInventory, formatWorktreeDirective, getAdapter, getBrightsySession, getDefaultRunScript, getDiff, getDiffSummary, getGitHubStatus, getIssueSource, getLinearApiKey, getOrchestrator, getPr, getPrChecks, getPrDetails, getPrMeta, getRepoSetupInfo, getRunMode, getRunScript, gh, ghHeadRef, ghRepoSelectArgs, git, globalAgentCwd, harnessEnvKey, hasConductorHook, hasCursorWorktreeSetup, hasRepoHook, hasWorkspaceHook, healOrchestrationSoccerTitles, importConductorWorkspace, importConductorWorkspaceAsync, initializeGitRepository, inspectGitWorktree, isBrightsyConnected, isBrightsyNdjsonLine, isCloudCoordinatorThread, isDirty, isGhRateLimitError, isGlobalRepoPath, isGlobalThread, isLinearConnected, isOrchestratorThread, isPlaceholderBranch, listBranchCommits, listBranches, listBrightsyAccounts, listBrightsyChatTargets, listConductorWorkspaces, listConnectedBrightsyTeams, listGitHubIssues, listGlobalThreads, listIssues, listLinearIssues, listLinearIssuesDirect, listPrs, listRunScripts, listThreads, listWorkspaces, listWorktreeFiles, listWorktrees, loadAgentInstructions, loadAppSettings, loadBrightsyConfig, loadConductorSettings, loadRepoSettings, loadWorkspaceSettings, locksDir, lookupSoccerTeam, maxConcurrentAgents, maybeCompactContext, mcpAllowTools, mcpAuthWarnings, mergePr, mergeUsage, normalizeParseResult, normalizeThread, normalizeTurnInput, normalizeWorktreePath, opencodeAdapter, orchestrationTitleNeedsSoccerNickname, orchestratorSessionPoisonedByBuiltins, originGhRepoEnv, parseCursorRunnerLine, parseForceStopMessage, parseGithubSlugFromRemoteUrl, parseMcpList, partsToAssistantText, permissionMode, previewLand, pushBranch, readSkillBody, readThread, readWorktreeFile, readWorktreeFileForUpload, readWorktreeInclude, refreshGitHubAuth, removeWorkspace, removeWorktree, repoSlug, requireAgent, resolveClaudeExecutable, resolveConductorCursorAgentId, resolveDefaultBranch, resolveDiffBaseRef, resolveEffectiveIssueSource, resolveFilesToCopy, resolveGithubRepoSlug, resolvePrSelector, resolveRepoRoot, resolveWorktreeStartPoint, run, runArchiveScript, runCloudConnect, runCursorWorktreeSetup, runSetupScript, sameWorktreePath, sanitizeMcpServerName, saveAppSettings, setStatus, settingsSourceLabel, shouldCompactContext, shouldRunWorktreeCleanup, sideboardHomeDir, sideboardReposDir, sideboardWorkspacesDir, slugify, spawnAgentTurn, splitForCompaction, startDevServer, startMcpServer, startOrchestration, stripBrightsyNdjsonNoise, suggestSlug, summarizeConversation, switchBrightsyAccount, syncWorkspacesFromThreads, takenTeamSlugsForChatTab, takenTeamSlugsForOrchestration, taskMessageText, threadDisplayLabel, threadFilePath, threadLockPath, threadsDir, threadsSharingWorktree, toolDescription, toolDetail, toolFilePath, totalTokens, updateAdvancedSettings, updateAppEnvironment, updateBrightsySettings, updateClaudeSettings, updateIntegrationsSettings, updateThread, validateLinearApiKey, withAgentInstructions, withThreadLock, workspaceSettingsSourceLabel, worktreeCleanupSettings, worktreeDisplayLabel, worktreeDisplayLabelForGroup, worktreeNameFromPath, worktreesRoot, writeInjectedMcpConfig, writeThread, writeWorktreeFile };
package/dist/index.js CHANGED
@@ -34,6 +34,7 @@ import {
34
34
  forkMessageSlice,
35
35
  forkThreadWorktree,
36
36
  formatAgentInstructions,
37
+ formatArtifactDirective,
37
38
  formatMessagesAsTranscript,
38
39
  formatRenameBranchDirective,
39
40
  formatTranscriptMarkdown,
@@ -66,6 +67,7 @@ import {
66
67
  previewLand,
67
68
  readSkillBody,
68
69
  readWorktreeFile,
70
+ readWorktreeFileForUpload,
69
71
  readWorktreeInclude,
70
72
  requireAgent,
71
73
  resolveConductorCursorAgentId,
@@ -93,7 +95,7 @@ import {
93
95
  withAgentInstructions,
94
96
  worktreeCleanupSettings,
95
97
  writeWorktreeFile
96
- } from "./chunk-ULFES3M5.js";
98
+ } from "./chunk-JNMLRJ3D.js";
97
99
  import {
98
100
  addWorkspace,
99
101
  ensureWorkspace,
@@ -158,7 +160,7 @@ import {
158
160
  permissionMode,
159
161
  sanitizeMcpServerName,
160
162
  writeInjectedMcpConfig
161
- } from "./chunk-V54GKKCI.js";
163
+ } from "./chunk-WK6AK7NK.js";
162
164
  import {
163
165
  brightsyConfigPath,
164
166
  brightsyMcpServerName,
@@ -824,6 +826,7 @@ export {
824
826
  forkMessageSlice,
825
827
  forkThreadWorktree,
826
828
  formatAgentInstructions,
829
+ formatArtifactDirective,
827
830
  formatBrightsyFetchError,
828
831
  formatGhLandError,
829
832
  formatIpcInvokeError,
@@ -924,6 +927,7 @@ export {
924
927
  readSkillBody,
925
928
  readThread,
926
929
  readWorktreeFile,
930
+ readWorktreeFileForUpload,
927
931
  readWorktreeInclude,
928
932
  refreshGitHubAuth,
929
933
  removeWorkspace,
@@ -3730,10 +3730,6 @@ function findSideboardMcpJsEntry() {
3730
3730
  return null;
3731
3731
  }
3732
3732
  async function resolveSideboardMcpServer() {
3733
- const which = await run("which", ["sideboard"], { reject: false });
3734
- if (which.exitCode === 0 && which.stdout.trim()) {
3735
- return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
3736
- }
3737
3733
  const entry = findSideboardMcpJsEntry();
3738
3734
  if (entry) {
3739
3735
  const isCli = /[/\\]cli[/\\]dist[/\\]index\.js$/.test(entry);
@@ -3744,6 +3740,10 @@ async function resolveSideboardMcpServer() {
3744
3740
  args: isCli ? [entry, "mcp"] : [entry]
3745
3741
  };
3746
3742
  }
3743
+ const which = await run("which", ["sideboard"], { reject: false });
3744
+ if (which.exitCode === 0 && which.stdout.trim()) {
3745
+ return { name: "sideboard", command: which.stdout.trim(), args: ["mcp"] };
3746
+ }
3747
3747
  return { name: "sideboard", command: "sideboard", args: ["mcp"] };
3748
3748
  }
3749
3749
  async function buildInjectedMcpServers(opts) {
@@ -3783,7 +3783,7 @@ function writeMcpServersConfig(servers) {
3783
3783
  (0, import_node_fs9.writeFileSync)(cfgPath, JSON.stringify({ mcpServers }, null, 2));
3784
3784
  return cfgPath;
3785
3785
  }
3786
- var import_node_fs9, import_node_module, import_node_os6, import_node_path10, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache;
3786
+ var import_node_fs9, import_node_module, import_node_os6, import_node_path10, import_node_url, import_meta, SIDEBOARD_MCP_ALLOWED_TOOLS, SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS, brightsyMcpCommandCache;
3787
3787
  var init_injected_mcp = __esm({
3788
3788
  "src/agents/injected-mcp.ts"() {
3789
3789
  "use strict";
@@ -3800,6 +3800,11 @@ var init_injected_mcp = __esm({
3800
3800
  "mcp__sideboard",
3801
3801
  "mcp__sideboard__*"
3802
3802
  ];
3803
+ SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS = [
3804
+ "mcp__sideboard__present_artifact",
3805
+ "mcp__sideboard__present_schema",
3806
+ "mcp__sideboard__present_files"
3807
+ ];
3803
3808
  brightsyMcpCommandCache = null;
3804
3809
  }
3805
3810
  });
@@ -4007,7 +4012,7 @@ var init_claude = __esm({
4007
4012
  const { isOrchestratorThread: isOrchestratorThread2 } = await Promise.resolve().then(() => (init_global_workspace(), global_workspace_exports));
4008
4013
  const isOrchestrator = isOrchestratorThread2(thread);
4009
4014
  const injectedServers = await buildInjectedMcpServers({
4010
- includeSideboard: isOrchestrator,
4015
+ includeSideboard: true,
4011
4016
  includeBrightsy: isBrightsyConnected()
4012
4017
  });
4013
4018
  const injectedBrightsyNames = injectedServers.filter((s) => s.name === "brightsy" || s.name.startsWith("brightsy_")).map((s) => s.name);
@@ -4024,6 +4029,7 @@ var init_claude = __esm({
4024
4029
  allowedTools = [
4025
4030
  ...BASE_ALLOWED_TOOLS,
4026
4031
  ...mcpAllowTools(servers),
4032
+ ...SIDEBOARD_ARTIFACT_MCP_ALLOWED_TOOLS,
4027
4033
  ...brightsyMcpAllowedTools(injectedBrightsyNames)
4028
4034
  ];
4029
4035
  }
@@ -4978,6 +4984,18 @@ function toolDescription(name, input) {
4978
4984
  if (/connectedAgentRequest/i.test(name)) {
4979
4985
  return str(input?.agent_id) ? `Ask connected agent` : "Ask connected agent";
4980
4986
  }
4987
+ if (/present_artifact$/i.test(name)) {
4988
+ return str(input?.title) ? `Present ${str(input?.title)}` : "Present artifact";
4989
+ }
4990
+ if (/present_schema$/i.test(name)) {
4991
+ return str(input?.title) ? `Schema ${str(input?.title)}` : "Present schema";
4992
+ }
4993
+ if (/present_files$/i.test(name)) {
4994
+ return str(input?.title) ? `Files ${str(input?.title)}` : "Present files";
4995
+ }
4996
+ if (/^(create|update)_artifact$/i.test(name.replace(/^mcp__[^_]+__/, ""))) {
4997
+ return str(input?.title) ? `Artifact ${str(input?.title)}` : "Artifact";
4998
+ }
4981
4999
  if (!input) return n;
4982
5000
  if (/bash|shell|terminal/i.test(name) && str(input.command)) {
4983
5001
  const cmd = str(input.command);
@@ -7064,6 +7082,27 @@ function isImageRelativePath(relativePath) {
7064
7082
  const ext = base.includes(".") ? base.split(".").pop() || "" : "";
7065
7083
  return IMAGE_EXTENSIONS.has(ext);
7066
7084
  }
7085
+ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
7086
+ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
7087
+ assertSafeRelativePath(relativePath);
7088
+ const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
7089
+ const abs = (0, import_node_path19.join)(worktreePath, relativePath);
7090
+ const st = (0, import_node_fs20.statSync)(abs);
7091
+ if (!st.isFile()) {
7092
+ throw new Error(`Not a file: ${relativePath}`);
7093
+ }
7094
+ if (st.size > maxBytes) {
7095
+ throw new Error(
7096
+ `File too large to upload (${st.size} bytes; max ${maxBytes})`
7097
+ );
7098
+ }
7099
+ const buf = (0, import_node_fs20.readFileSync)(abs);
7100
+ return {
7101
+ path: relativePath,
7102
+ contentBase64: buf.toString("base64"),
7103
+ size: buf.length
7104
+ };
7105
+ }
7067
7106
  function readWorktreeFile(worktreePath, relativePath, opts) {
7068
7107
  assertSafeRelativePath(relativePath);
7069
7108
  const maxBytes = opts?.maxBytes ?? 2e5;
@@ -7592,6 +7631,26 @@ function formatWorktreeDirective(thread, opts) {
7592
7631
  }
7593
7632
  return lines.join("\n");
7594
7633
  }
7634
+ function formatArtifactDirective() {
7635
+ return [
7636
+ "Sideboard side column (desktop UI):",
7637
+ "claude.ai\u2019s \u201CArtifact\u201D tool does NOT exist in Claude Code. That is expected.",
7638
+ "Documents (HTML/SVG/markdown):",
7639
+ "1) Emit a fenced code block tagged `html` (preferred), `svg`, or `markdown` with the FULL document \u2014 Sideboard opens a side column. Example:",
7640
+ "```html",
7641
+ "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
7642
+ "```",
7643
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content.",
7644
+ "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
7645
+ "3) Call Sideboard MCP `present_schema` with title, mode (table|form), and either:",
7646
+ " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
7647
+ " - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
7648
+ "Files / media browser (CMS file manager column):",
7649
+ "4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
7650
+ " Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
7651
+ "Never say artifacts, CMS UI, or the Files column are unavailable. Prefer present_schema for list/edit/publish; present_files for storage UI; html fences for standalone pages."
7652
+ ].join("\n");
7653
+ }
7595
7654
  var FILES_BY_AGENT = {
7596
7655
  claude: [
7597
7656
  "CLAUDE.md",
@@ -7926,9 +7985,18 @@ var Orchestrator = class {
7926
7985
  parentId: threadId,
7927
7986
  goal: thread.sourceRef || thread.title
7928
7987
  }) : null;
7988
+ const artifactReminder = thread.agent !== "brightsy" ? [
7989
+ "Sideboard side column (important):",
7990
+ "There is no claude.ai Artifact tool here \u2014 that is normal.",
7991
+ "HTML/SVG/markdown: ```html fence or MCP present_artifact.",
7992
+ "CMS forms/tables: MCP present_schema (Brightsy resource_id or inline schema+schemaUi).",
7993
+ "Files column: MCP present_files (brightsy account storage or memory).",
7994
+ "Do not say artifacts/CMS UI are unavailable."
7995
+ ].join(" ") : null;
7929
7996
  const agentPrompt = [
7930
7997
  thread.planMode ? PLAN_MODE_INSTRUCTION : null,
7931
7998
  orchestrationReminder,
7999
+ artifactReminder,
7932
8000
  expandedPrompt
7933
8001
  ].filter(Boolean).join("\n\n");
7934
8002
  const instructionFiles = loadAgentInstructions(thread.worktreePath, thread.agent);
@@ -7953,6 +8021,7 @@ var Orchestrator = class {
7953
8021
  () => null
7954
8022
  )
7955
8023
  });
8024
+ const artifactDirective = isBrightsy ? null : formatArtifactDirective();
7956
8025
  const settings = loadWorkspaceSettings(fresh.worktreePath, fresh.repoPath);
7957
8026
  const { autoRenameBranchEnabled: autoRenameBranchEnabled2 } = await Promise.resolve().then(() => (init_app_settings(), app_settings_exports));
7958
8027
  const renameBranchDirective = !isBrightsy && !isOrchestration && autoRenameBranchEnabled2() ? formatRenameBranchDirective(fresh, {
@@ -7980,6 +8049,7 @@ var Orchestrator = class {
7980
8049
  const cachedPrefix = [
7981
8050
  coordinatorDirective,
7982
8051
  worktreeDirective,
8052
+ artifactDirective,
7983
8053
  renameBranchDirective,
7984
8054
  ...fresh.agent === "claude" && fresh.sessionId ? [] : [instructions, seed]
7985
8055
  ].filter(Boolean).join("\n\n---\n\n");
@@ -8400,6 +8470,13 @@ var Orchestrator = class {
8400
8470
  }
8401
8471
  return readWorktreeFile(thread.worktreePath, relativePath);
8402
8472
  }
8473
+ async readFileForUpload(threadRef, relativePath) {
8474
+ const thread = this.requireThread(threadRef);
8475
+ if (relativePath.includes("..") || relativePath.startsWith("/")) {
8476
+ throw new Error("Invalid path");
8477
+ }
8478
+ return readWorktreeFileForUpload(thread.worktreePath, relativePath);
8479
+ }
8403
8480
  async writeFile(threadRef, relativePath, content) {
8404
8481
  const thread = this.requireThread(threadRef);
8405
8482
  if (relativePath.includes("..") || relativePath.startsWith("/")) {
@@ -8849,6 +8926,82 @@ async function startMcpServer() {
8849
8926
  return { content: [{ type: "text", text: JSON.stringify(summary, null, 2) }] };
8850
8927
  }
8851
8928
  );
8929
+ server.tool(
8930
+ "present_artifact",
8931
+ "Show an HTML, SVG, or markdown document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Prefer type=html for interactive pages.",
8932
+ {
8933
+ title: import_zod.z.string().describe("Short title shown in the artifact pane header"),
8934
+ type: import_zod.z.enum(["html", "svg", "markdown"]).describe("Artifact kind \u2014 html opens an iframe preview"),
8935
+ content: import_zod.z.string().describe("Full document body (complete HTML page, SVG markup, or markdown)"),
8936
+ artifact_id: import_zod.z.string().optional().describe("Stable id when updating the same artifact across turns")
8937
+ },
8938
+ async ({ title, type, content, artifact_id }) => {
8939
+ const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8940
+ const payload = {
8941
+ ok: true,
8942
+ artifact_id: id,
8943
+ title,
8944
+ type,
8945
+ content,
8946
+ message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
8947
+ };
8948
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
8949
+ }
8950
+ );
8951
+ server.tool(
8952
+ "present_schema",
8953
+ "Open Sideboard\u2019s schema-driven CMS side column (filterable table and/or form). Pass JSON Schema + schemaUi (Brightsy extensions supported). Use datasource=brightsy with resource_id (record type UUID) when logged into Brightsy; use datasource=inline with embedded resource/records for any other source.",
8954
+ {
8955
+ title: import_zod.z.string().describe("Pane title"),
8956
+ mode: import_zod.z.enum(["table", "form"]).optional().describe("table = list/filter records; form = edit one record"),
8957
+ datasource: import_zod.z.enum(["brightsy", "inline"]).optional().describe("brightsy resolves via login; inline uses embedded resource/records"),
8958
+ resource_id: import_zod.z.string().optional().describe("Brightsy record type UUID (or generic resource id)"),
8959
+ record_id: import_zod.z.string().optional().describe("Record id when opening form mode"),
8960
+ resource: import_zod.z.record(import_zod.z.unknown()).optional().describe("Inline { id, title, schema, schemaUi?, slug? }"),
8961
+ record: import_zod.z.record(import_zod.z.unknown()).optional().describe("Inline record { id, data, published_at? }"),
8962
+ records: import_zod.z.array(import_zod.z.record(import_zod.z.unknown())).optional().describe("Inline records for table mode"),
8963
+ pane_id: import_zod.z.string().optional().describe("Stable pane id across updates")
8964
+ },
8965
+ async (args) => {
8966
+ const id = args.pane_id?.trim() || `schema_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8967
+ const payload = {
8968
+ ok: true,
8969
+ pane_id: id,
8970
+ title: args.title,
8971
+ mode: args.mode ?? (args.record_id || args.record ? "form" : "table"),
8972
+ datasource: args.datasource ?? (args.resource ? "inline" : "brightsy"),
8973
+ resource_id: args.resource_id,
8974
+ record_id: args.record_id,
8975
+ resource: args.resource,
8976
+ record: args.record,
8977
+ records: args.records,
8978
+ message: "Schema pane accepted. Sideboard desktop opens the CMS column beside chat."
8979
+ };
8980
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
8981
+ }
8982
+ );
8983
+ server.tool(
8984
+ "present_files",
8985
+ "Open Sideboard\u2019s Files column (CMS-style file manager: browse, upload, pick). Use datasource=brightsy when the user is logged into Brightsy account storage; datasource=memory for a session-local demo store. Prefer this over claiming a file manager UI is unavailable. Pair with present_schema when editing records that need media.",
8986
+ {
8987
+ title: import_zod.z.string().optional().describe("Pane title (default: Files)"),
8988
+ datasource: import_zod.z.enum(["brightsy", "memory"]).optional().describe("brightsy = account storage via login; memory = session demo store"),
8989
+ path: import_zod.z.string().optional().describe("Initial folder path (e.g. public)"),
8990
+ pane_id: import_zod.z.string().optional().describe("Stable pane id across updates")
8991
+ },
8992
+ async (args) => {
8993
+ const id = args.pane_id?.trim() || `files_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
8994
+ const payload = {
8995
+ ok: true,
8996
+ pane_id: id,
8997
+ title: args.title?.trim() || "Files",
8998
+ datasource: args.datasource ?? "brightsy",
8999
+ path: args.path,
9000
+ message: "Files pane accepted. Sideboard desktop opens the Files column beside chat."
9001
+ };
9002
+ return { content: [{ type: "text", text: JSON.stringify(payload) }] };
9003
+ }
9004
+ );
8852
9005
  server.tool(
8853
9006
  "create_thread",
8854
9007
  "Create a new worktree thread (chat) from branch, pr, or ticket. Pass repoPath from list_workspaces and parentThreadId when spawning from an orchestrator. Then use send_to_thread to chat.",
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startMcpServer
4
- } from "../chunk-ULFES3M5.js";
4
+ } from "../chunk-JNMLRJ3D.js";
5
5
  import "../chunk-PER4N6LS.js";
6
6
  import "../chunk-Y2EWQ4TL.js";
7
7
  import "../chunk-BMB7WCGF.js";
8
- import "../chunk-V54GKKCI.js";
8
+ import "../chunk-WK6AK7NK.js";
9
9
  import "../chunk-ILQK4P5R.js";
10
10
  import "../chunk-3DKGI32Q.js";
11
11
  import "../chunk-3WF3X46L.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.22",
3
+ "version": "0.1.23",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",