@sideboard-ai/core 0.1.127 → 0.1.130

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.
@@ -380,7 +380,7 @@ async function continueSourceThread(threadId, prompt) {
380
380
  await continueOnReply(threadId, prompt);
381
381
  return;
382
382
  }
383
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-3JLPPTCF.js");
383
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-3ZSFTG72.js");
384
384
  await getOrchestrator2().send(threadId, prompt);
385
385
  } catch {
386
386
  }
@@ -5054,7 +5054,8 @@ function formatArtifactDirective() {
5054
5054
  "```html",
5055
5055
  "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
5056
5056
  "```",
5057
- "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content \u2014 not both a fence and this tool for the same body.",
5057
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
5058
+ " type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
5058
5059
  "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
5059
5060
  "3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
5060
5061
  " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
@@ -5069,7 +5070,7 @@ function formatArtifactDirective() {
5069
5070
  ].join("\n");
5070
5071
  }
5071
5072
  function formatUiReminder() {
5072
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
5073
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
5073
5074
  }
5074
5075
 
5075
5076
  // src/threads/sync-branch.ts
@@ -5340,7 +5341,7 @@ function formatScheduledPrompt(name, prompt) {
5340
5341
  ${prompt}`;
5341
5342
  }
5342
5343
  async function defaultDeps() {
5343
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-3JLPPTCF.js");
5344
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-3ZSFTG72.js");
5344
5345
  const orch = getOrchestrator2();
5345
5346
  return {
5346
5347
  findThread: (id) => findThreadByRef(id),
@@ -441,7 +441,7 @@ async function continueSourceThread(threadId, prompt) {
441
441
  await continueOnReply(threadId, prompt);
442
442
  return;
443
443
  }
444
- const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6GUCE4LY.js");
444
+ const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-G6DU3AF3.js");
445
445
  await getOrchestrator2().send(threadId, prompt);
446
446
  } catch {
447
447
  }
@@ -5145,7 +5145,8 @@ function formatArtifactDirective() {
5145
5145
  "```html",
5146
5146
  "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
5147
5147
  "```",
5148
- "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content \u2014 not both a fence and this tool for the same body.",
5148
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
5149
+ " type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
5149
5150
  "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
5150
5151
  "3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
5151
5152
  " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
@@ -5160,7 +5161,7 @@ function formatArtifactDirective() {
5160
5161
  ].join("\n");
5161
5162
  }
5162
5163
  function formatUiReminder() {
5163
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
5164
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
5164
5165
  }
5165
5166
  var FILES_BY_AGENT = {
5166
5167
  claude: [
@@ -5505,7 +5506,7 @@ function formatScheduledPrompt(name, prompt) {
5505
5506
  ${prompt}`;
5506
5507
  }
5507
5508
  async function defaultDeps() {
5508
- const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-6GUCE4LY.js");
5509
+ const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-G6DU3AF3.js");
5509
5510
  const orch = getOrchestrator2();
5510
5511
  return {
5511
5512
  findThread: (id) => findThreadByRef(id),
package/dist/index.cjs CHANGED
@@ -15868,7 +15868,8 @@ function formatArtifactDirective() {
15868
15868
  "```html",
15869
15869
  "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
15870
15870
  "```",
15871
- "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content \u2014 not both a fence and this tool for the same body.",
15871
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
15872
+ " type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
15872
15873
  "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
15873
15874
  "3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
15874
15875
  " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
@@ -15883,7 +15884,7 @@ function formatArtifactDirective() {
15883
15884
  ].join("\n");
15884
15885
  }
15885
15886
  function formatUiReminder() {
15886
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
15887
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
15887
15888
  }
15888
15889
  function loadAgentInstructions(worktreePath, agent) {
15889
15890
  const candidates = FILES_BY_AGENT[agent] ?? FILES_BY_AGENT.claude;
@@ -19264,6 +19265,16 @@ async function disconnectLinear() {
19264
19265
 
19265
19266
  // src/integrations/linear.ts
19266
19267
  var LINEAR_GRAPHQL2 = "https://api.linear.app/graphql";
19268
+ var LIST_ISSUE_FIELDS = `
19269
+ id
19270
+ identifier
19271
+ title
19272
+ url
19273
+ assignee { id name }
19274
+ team { id key }
19275
+ labels(first: 10) { nodes { name } }
19276
+ cycle { name number startsAt endsAt completedAt }
19277
+ `;
19267
19278
  var ISSUE_FIELDS = `
19268
19279
  id
19269
19280
  identifier
@@ -19273,9 +19284,9 @@ var ISSUE_FIELDS = `
19273
19284
  priority
19274
19285
  state { id name type }
19275
19286
  assignee { id name }
19276
- team { id key name states { nodes { id name type } } }
19277
- labels { nodes { name } }
19278
- cycle { id name number startsAt endsAt completedAt }
19287
+ team { id key name states(first: 50) { nodes { id name type } } }
19288
+ labels(first: 50) { nodes { name } }
19289
+ cycle { name number startsAt endsAt completedAt }
19279
19290
  `;
19280
19291
  var ASSIGNED_ISSUES_QUERY = `
19281
19292
  query SideboardAssignedIssues($first: Int!) {
@@ -19287,7 +19298,7 @@ query SideboardAssignedIssues($first: Int!) {
19287
19298
  orderBy: updatedAt
19288
19299
  filter: { state: { type: { nin: ["completed", "canceled"] } } }
19289
19300
  ) {
19290
- nodes { ${ISSUE_FIELDS} }
19301
+ nodes { ${LIST_ISSUE_FIELDS} }
19291
19302
  }
19292
19303
  }
19293
19304
  }
@@ -19300,7 +19311,7 @@ query SideboardTeams {
19300
19311
  id
19301
19312
  key
19302
19313
  name
19303
- states { nodes { id name type } }
19314
+ states(first: 50) { nodes { id name type } }
19304
19315
  }
19305
19316
  }
19306
19317
  }
@@ -21280,25 +21291,31 @@ async function startMcpServer() {
21280
21291
  }
21281
21292
  server.tool(
21282
21293
  "present_artifact",
21283
- "Show an HTML, SVG, markdown, or React document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Do not also emit the same document as a chat html/markdown fence. Prefer type=html for interactive pages. For type=react, pass a single component module that `export default`s a component (JSX/TSX ok) \u2014 Sideboard bootstraps React/ReactDOM/Babel and renders it; only `react`/`react-dom` imports are available, no other npm packages.",
21294
+ "Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
21284
21295
  {
21285
21296
  title: import_zod4.z.string().describe("Short title shown in the artifact pane header"),
21286
- type: import_zod4.z.enum(["html", "svg", "markdown", "react"]).describe(
21287
- "Artifact kind \u2014 html opens an iframe preview; react transpiles and renders a default-exported component in a sandboxed iframe"
21297
+ type: import_zod4.z.enum(["html", "svg", "markdown", "react", "log"]).describe(
21298
+ "html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
21288
21299
  ),
21289
21300
  content: import_zod4.z.string().describe(
21290
- "Full document body (complete HTML page, SVG markup, markdown, or a React component module with a default export)"
21301
+ "html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
21291
21302
  ),
21292
- artifact_id: import_zod4.z.string().optional().describe("Stable id when updating the same artifact across turns")
21303
+ artifact_id: import_zod4.z.string().optional().describe("Stable id. Required for type=log so later calls append to the same pane."),
21304
+ status: import_zod4.z.enum(["running", "ok", "failed", "idle"]).optional().describe("Log header pill: running (working), ok (done), failed, idle"),
21305
+ phase: import_zod4.z.string().optional().describe("Log subtitle (Signing, Notarizing, \u2026)"),
21306
+ mode: import_zod4.z.enum(["append", "replace"]).optional().describe("log only: append (default) or replace the buffer")
21293
21307
  },
21294
- async ({ title, type, artifact_id }) => {
21308
+ async ({ title, type, artifact_id, status, phase, mode }) => {
21295
21309
  const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
21296
21310
  const payload = {
21297
21311
  ok: true,
21298
21312
  artifact_id: id,
21299
21313
  title,
21300
21314
  type,
21301
- message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
21315
+ status,
21316
+ phase,
21317
+ mode: type === "log" ? mode ?? "append" : void 0,
21318
+ message: type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
21302
21319
  };
21303
21320
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
21304
21321
  }
package/dist/index.js CHANGED
@@ -185,7 +185,7 @@ import {
185
185
  worktreeCleanupSettings,
186
186
  wrapReviewSkillMarkdown,
187
187
  writeWorktreeFile
188
- } from "./chunk-T7KJQJAX.js";
188
+ } from "./chunk-YALVX3UE.js";
189
189
  import {
190
190
  BRIGHTSY_MCP_ALLOWED_TOOLS,
191
191
  CLAUDE_MODEL_CATALOG,
@@ -919,6 +919,16 @@ async function disconnectLinear() {
919
919
 
920
920
  // src/integrations/linear.ts
921
921
  var LINEAR_GRAPHQL2 = "https://api.linear.app/graphql";
922
+ var LIST_ISSUE_FIELDS = `
923
+ id
924
+ identifier
925
+ title
926
+ url
927
+ assignee { id name }
928
+ team { id key }
929
+ labels(first: 10) { nodes { name } }
930
+ cycle { name number startsAt endsAt completedAt }
931
+ `;
922
932
  var ISSUE_FIELDS = `
923
933
  id
924
934
  identifier
@@ -928,9 +938,9 @@ var ISSUE_FIELDS = `
928
938
  priority
929
939
  state { id name type }
930
940
  assignee { id name }
931
- team { id key name states { nodes { id name type } } }
932
- labels { nodes { name } }
933
- cycle { id name number startsAt endsAt completedAt }
941
+ team { id key name states(first: 50) { nodes { id name type } } }
942
+ labels(first: 50) { nodes { name } }
943
+ cycle { name number startsAt endsAt completedAt }
934
944
  `;
935
945
  var ASSIGNED_ISSUES_QUERY = `
936
946
  query SideboardAssignedIssues($first: Int!) {
@@ -942,7 +952,7 @@ query SideboardAssignedIssues($first: Int!) {
942
952
  orderBy: updatedAt
943
953
  filter: { state: { type: { nin: ["completed", "canceled"] } } }
944
954
  ) {
945
- nodes { ${ISSUE_FIELDS} }
955
+ nodes { ${LIST_ISSUE_FIELDS} }
946
956
  }
947
957
  }
948
958
  }
@@ -955,7 +965,7 @@ query SideboardTeams {
955
965
  id
956
966
  key
957
967
  name
958
- states { nodes { id name type } }
968
+ states(first: 50) { nodes { id name type } }
959
969
  }
960
970
  }
961
971
  }
@@ -2862,25 +2872,31 @@ async function startMcpServer() {
2862
2872
  }
2863
2873
  server.tool(
2864
2874
  "present_artifact",
2865
- "Show an HTML, SVG, markdown, or React document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Do not also emit the same document as a chat html/markdown fence. Prefer type=html for interactive pages. For type=react, pass a single component module that `export default`s a component (JSX/TSX ok) \u2014 Sideboard bootstraps React/ReactDOM/Babel and renders it; only `react`/`react-dom` imports are available, no other npm packages.",
2875
+ "Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
2866
2876
  {
2867
2877
  title: z4.string().describe("Short title shown in the artifact pane header"),
2868
- type: z4.enum(["html", "svg", "markdown", "react"]).describe(
2869
- "Artifact kind \u2014 html opens an iframe preview; react transpiles and renders a default-exported component in a sandboxed iframe"
2878
+ type: z4.enum(["html", "svg", "markdown", "react", "log"]).describe(
2879
+ "html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
2870
2880
  ),
2871
2881
  content: z4.string().describe(
2872
- "Full document body (complete HTML page, SVG markup, markdown, or a React component module with a default export)"
2882
+ "html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
2873
2883
  ),
2874
- artifact_id: z4.string().optional().describe("Stable id when updating the same artifact across turns")
2884
+ artifact_id: z4.string().optional().describe("Stable id. Required for type=log so later calls append to the same pane."),
2885
+ status: z4.enum(["running", "ok", "failed", "idle"]).optional().describe("Log header pill: running (working), ok (done), failed, idle"),
2886
+ phase: z4.string().optional().describe("Log subtitle (Signing, Notarizing, \u2026)"),
2887
+ mode: z4.enum(["append", "replace"]).optional().describe("log only: append (default) or replace the buffer")
2875
2888
  },
2876
- async ({ title, type, artifact_id }) => {
2889
+ async ({ title, type, artifact_id, status, phase, mode }) => {
2877
2890
  const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
2878
2891
  const payload = {
2879
2892
  ok: true,
2880
2893
  artifact_id: id,
2881
2894
  title,
2882
2895
  type,
2883
- message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
2896
+ status,
2897
+ phase,
2898
+ mode: type === "log" ? mode ?? "append" : void 0,
2899
+ message: type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
2884
2900
  };
2885
2901
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
2886
2902
  }
@@ -14901,7 +14901,8 @@ function formatArtifactDirective() {
14901
14901
  "```html",
14902
14902
  "<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
14903
14903
  "```",
14904
- "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown), and content \u2014 not both a fence and this tool for the same body.",
14904
+ "2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
14905
+ " type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
14905
14906
  "CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
14906
14907
  "3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
14907
14908
  " - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
@@ -14916,7 +14917,7 @@ function formatArtifactDirective() {
14916
14917
  ].join("\n");
14917
14918
  }
14918
14919
  function formatUiReminder() {
14919
- return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
14920
+ return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
14920
14921
  }
14921
14922
  var import_node_fs40, import_node_path37;
14922
14923
  var init_instructions = __esm({
@@ -17799,6 +17800,16 @@ async function getLinearAuthToken(settings = loadAppSettings()) {
17799
17800
 
17800
17801
  // src/integrations/linear.ts
17801
17802
  var LINEAR_GRAPHQL = "https://api.linear.app/graphql";
17803
+ var LIST_ISSUE_FIELDS = `
17804
+ id
17805
+ identifier
17806
+ title
17807
+ url
17808
+ assignee { id name }
17809
+ team { id key }
17810
+ labels(first: 10) { nodes { name } }
17811
+ cycle { name number startsAt endsAt completedAt }
17812
+ `;
17802
17813
  var ISSUE_FIELDS = `
17803
17814
  id
17804
17815
  identifier
@@ -17808,9 +17819,9 @@ var ISSUE_FIELDS = `
17808
17819
  priority
17809
17820
  state { id name type }
17810
17821
  assignee { id name }
17811
- team { id key name states { nodes { id name type } } }
17812
- labels { nodes { name } }
17813
- cycle { id name number startsAt endsAt completedAt }
17822
+ team { id key name states(first: 50) { nodes { id name type } } }
17823
+ labels(first: 50) { nodes { name } }
17824
+ cycle { name number startsAt endsAt completedAt }
17814
17825
  `;
17815
17826
  var ASSIGNED_ISSUES_QUERY = `
17816
17827
  query SideboardAssignedIssues($first: Int!) {
@@ -17822,7 +17833,7 @@ query SideboardAssignedIssues($first: Int!) {
17822
17833
  orderBy: updatedAt
17823
17834
  filter: { state: { type: { nin: ["completed", "canceled"] } } }
17824
17835
  ) {
17825
- nodes { ${ISSUE_FIELDS} }
17836
+ nodes { ${LIST_ISSUE_FIELDS} }
17826
17837
  }
17827
17838
  }
17828
17839
  }
@@ -17835,7 +17846,7 @@ query SideboardTeams {
17835
17846
  id
17836
17847
  key
17837
17848
  name
17838
- states { nodes { id name type } }
17849
+ states(first: 50) { nodes { id name type } }
17839
17850
  }
17840
17851
  }
17841
17852
  }
@@ -19490,25 +19501,31 @@ async function startMcpServer() {
19490
19501
  }
19491
19502
  server.tool(
19492
19503
  "present_artifact",
19493
- "Show an HTML, SVG, markdown, or React document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Do not also emit the same document as a chat html/markdown fence. Prefer type=html for interactive pages. For type=react, pass a single component module that `export default`s a component (JSX/TSX ok) \u2014 Sideboard bootstraps React/ReactDOM/Babel and renders it; only `react`/`react-dom` imports are available, no other npm packages.",
19504
+ "Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
19494
19505
  {
19495
19506
  title: import_zod4.z.string().describe("Short title shown in the artifact pane header"),
19496
- type: import_zod4.z.enum(["html", "svg", "markdown", "react"]).describe(
19497
- "Artifact kind \u2014 html opens an iframe preview; react transpiles and renders a default-exported component in a sandboxed iframe"
19507
+ type: import_zod4.z.enum(["html", "svg", "markdown", "react", "log"]).describe(
19508
+ "html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
19498
19509
  ),
19499
19510
  content: import_zod4.z.string().describe(
19500
- "Full document body (complete HTML page, SVG markup, markdown, or a React component module with a default export)"
19511
+ "html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
19501
19512
  ),
19502
- artifact_id: import_zod4.z.string().optional().describe("Stable id when updating the same artifact across turns")
19513
+ artifact_id: import_zod4.z.string().optional().describe("Stable id. Required for type=log so later calls append to the same pane."),
19514
+ status: import_zod4.z.enum(["running", "ok", "failed", "idle"]).optional().describe("Log header pill: running (working), ok (done), failed, idle"),
19515
+ phase: import_zod4.z.string().optional().describe("Log subtitle (Signing, Notarizing, \u2026)"),
19516
+ mode: import_zod4.z.enum(["append", "replace"]).optional().describe("log only: append (default) or replace the buffer")
19503
19517
  },
19504
- async ({ title, type, artifact_id }) => {
19518
+ async ({ title, type, artifact_id, status, phase, mode }) => {
19505
19519
  const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
19506
19520
  const payload = {
19507
19521
  ok: true,
19508
19522
  artifact_id: id,
19509
19523
  title,
19510
19524
  type,
19511
- message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
19525
+ status,
19526
+ phase,
19527
+ mode: type === "log" ? mode ?? "append" : void 0,
19528
+ message: type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
19512
19529
  };
19513
19530
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
19514
19531
  }
@@ -31,7 +31,7 @@ import {
31
31
  slackTokenFor,
32
32
  syncBoardPins,
33
33
  updateSchedule
34
- } from "../chunk-DLM5LSQW.js";
34
+ } from "../chunk-FMBLOOAO.js";
35
35
  import {
36
36
  listModelsForAgent,
37
37
  sideboardMcpProfile
@@ -201,6 +201,16 @@ async function getLinearAuthToken(settings = loadAppSettings()) {
201
201
 
202
202
  // src/integrations/linear.ts
203
203
  var LINEAR_GRAPHQL = "https://api.linear.app/graphql";
204
+ var LIST_ISSUE_FIELDS = `
205
+ id
206
+ identifier
207
+ title
208
+ url
209
+ assignee { id name }
210
+ team { id key }
211
+ labels(first: 10) { nodes { name } }
212
+ cycle { name number startsAt endsAt completedAt }
213
+ `;
204
214
  var ISSUE_FIELDS = `
205
215
  id
206
216
  identifier
@@ -210,9 +220,9 @@ var ISSUE_FIELDS = `
210
220
  priority
211
221
  state { id name type }
212
222
  assignee { id name }
213
- team { id key name states { nodes { id name type } } }
214
- labels { nodes { name } }
215
- cycle { id name number startsAt endsAt completedAt }
223
+ team { id key name states(first: 50) { nodes { id name type } } }
224
+ labels(first: 50) { nodes { name } }
225
+ cycle { name number startsAt endsAt completedAt }
216
226
  `;
217
227
  var ASSIGNED_ISSUES_QUERY = `
218
228
  query SideboardAssignedIssues($first: Int!) {
@@ -224,7 +234,7 @@ query SideboardAssignedIssues($first: Int!) {
224
234
  orderBy: updatedAt
225
235
  filter: { state: { type: { nin: ["completed", "canceled"] } } }
226
236
  ) {
227
- nodes { ${ISSUE_FIELDS} }
237
+ nodes { ${LIST_ISSUE_FIELDS} }
228
238
  }
229
239
  }
230
240
  }
@@ -237,7 +247,7 @@ query SideboardTeams {
237
247
  id
238
248
  key
239
249
  name
240
- states { nodes { id name type } }
250
+ states(first: 50) { nodes { id name type } }
241
251
  }
242
252
  }
243
253
  }
@@ -1864,25 +1874,31 @@ async function startMcpServer() {
1864
1874
  }
1865
1875
  server.tool(
1866
1876
  "present_artifact",
1867
- "Show an HTML, SVG, markdown, or React document in Sideboard\u2019s Claude-style side column (desktop). Use instead of claude.ai\u2019s artifact tool \u2014 pass the full document content. Do not also emit the same document as a chat html/markdown fence. Prefer type=html for interactive pages. For type=react, pass a single component module that `export default`s a component (JSX/TSX ok) \u2014 Sideboard bootstraps React/ReactDOM/Babel and renders it; only `react`/`react-dom` imports are available, no other npm packages.",
1877
+ "Show a document or live log in Sideboard\u2019s side column. For html/svg/markdown/react, pass the FULL document and do not also fence that same body in chat. For type=log, pass only NEW lines (same artifact_id appends). Prefer type=log for long-running job output \u2014 do not resend HTML. type=react is a single default-export component (JSX/TSX); only react/react-dom imports.",
1868
1878
  {
1869
1879
  title: z4.string().describe("Short title shown in the artifact pane header"),
1870
- type: z4.enum(["html", "svg", "markdown", "react"]).describe(
1871
- "Artifact kind \u2014 html opens an iframe preview; react transpiles and renders a default-exported component in a sandboxed iframe"
1880
+ type: z4.enum(["html", "svg", "markdown", "react", "log"]).describe(
1881
+ "html/svg/markdown/react replace the pane. log appends content to the same artifact_id (new lines only)."
1872
1882
  ),
1873
1883
  content: z4.string().describe(
1874
- "Full document body (complete HTML page, SVG markup, markdown, or a React component module with a default export)"
1884
+ "html/svg/markdown/react: full document. log: only the new lines since the last call (empty is ok for a status-only update)."
1875
1885
  ),
1876
- artifact_id: z4.string().optional().describe("Stable id when updating the same artifact across turns")
1886
+ artifact_id: z4.string().optional().describe("Stable id. Required for type=log so later calls append to the same pane."),
1887
+ status: z4.enum(["running", "ok", "failed", "idle"]).optional().describe("Log header pill: running (working), ok (done), failed, idle"),
1888
+ phase: z4.string().optional().describe("Log subtitle (Signing, Notarizing, \u2026)"),
1889
+ mode: z4.enum(["append", "replace"]).optional().describe("log only: append (default) or replace the buffer")
1877
1890
  },
1878
- async ({ title, type, artifact_id }) => {
1891
+ async ({ title, type, artifact_id, status, phase, mode }) => {
1879
1892
  const id = artifact_id?.trim() || `artifact_${Date.now().toString(36)}_${Math.random().toString(36).slice(2, 8)}`;
1880
1893
  const payload = {
1881
1894
  ok: true,
1882
1895
  artifact_id: id,
1883
1896
  title,
1884
1897
  type,
1885
- message: "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
1898
+ status,
1899
+ phase,
1900
+ mode: type === "log" ? mode ?? "append" : void 0,
1901
+ message: type === "log" ? "Log accepted. Same artifact_id appends; send only new lines next time." : "Artifact accepted. Sideboard desktop opens it in the side column beside chat."
1886
1902
  };
1887
1903
  return { content: [{ type: "text", text: JSON.stringify(payload) }] };
1888
1904
  }
@@ -6,7 +6,7 @@ import {
6
6
  isPidAlive,
7
7
  startOrchestration,
8
8
  waitForPidExit
9
- } from "./chunk-DLM5LSQW.js";
9
+ } from "./chunk-FMBLOOAO.js";
10
10
  import "./chunk-ZMUOPTKZ.js";
11
11
  import "./chunk-YMRT2DU6.js";
12
12
  import "./chunk-SYLTXDRF.js";
@@ -4,7 +4,7 @@ import {
4
4
  isPidAlive,
5
5
  startOrchestration,
6
6
  waitForPidExit
7
- } from "./chunk-T7KJQJAX.js";
7
+ } from "./chunk-YALVX3UE.js";
8
8
  import "./chunk-NV73AO7Q.js";
9
9
  import "./chunk-EKIDHL2T.js";
10
10
  import "./chunk-VE22NWBD.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sideboard-ai/core",
3
- "version": "0.1.127",
3
+ "version": "0.1.130",
4
4
  "description": "Sideboard core — orchestration, agents, git worktrees, MCP server",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",