@sidecar-ai/cli 0.1.0-alpha.13 → 0.1.0-alpha.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -4561,14 +4561,14 @@ function renderDevHarnessHtml(state, options = {}) {
4561
4561
  border: 1px solid var(--border);
4562
4562
  border-radius: 10px;
4563
4563
  display: block;
4564
- height: clamp(360px, 58dvh, 720px);
4565
- min-height: 360px;
4564
+ height: 360px;
4565
+ min-height: 0;
4566
4566
  overflow: auto;
4567
+ transition: height 120ms ease;
4567
4568
  width: 100%;
4568
4569
  }
4569
4570
  :root[data-sidecar-device="mobile"] .tool-body iframe {
4570
- height: clamp(440px, 70dvh, 680px);
4571
- min-height: 440px;
4571
+ height: 440px;
4572
4572
  }
4573
4573
 
4574
4574
  .composer {
@@ -5021,6 +5021,7 @@ async function readMcpResource(mcpUrl, uri, authToken) {
5021
5021
  };
5022
5022
  }
5023
5023
  async function callMcp(mcpUrl, method, params, authToken) {
5024
+ const requestId = randomUUID3();
5024
5025
  const response = await fetch(mcpUrl, {
5025
5026
  method: "POST",
5026
5027
  headers: {
@@ -5031,7 +5032,7 @@ async function callMcp(mcpUrl, method, params, authToken) {
5031
5032
  },
5032
5033
  body: JSON.stringify({
5033
5034
  jsonrpc: "2.0",
5034
- id: randomUUID3(),
5035
+ id: requestId,
5035
5036
  method,
5036
5037
  params
5037
5038
  })
@@ -5040,12 +5041,26 @@ async function callMcp(mcpUrl, method, params, authToken) {
5040
5041
  if (!response.ok) {
5041
5042
  throw new HttpError(response.status, `MCP ${method} failed with HTTP ${response.status}: ${text}`);
5042
5043
  }
5043
- const json = JSON.parse(text);
5044
+ const json = parseMcpResponse(text, response.headers.get("content-type"), requestId);
5044
5045
  if (json.error) {
5045
5046
  throw new HttpError(502, json.error.message ?? `MCP ${method} returned an error.`);
5046
5047
  }
5047
5048
  return json.result;
5048
5049
  }
5050
+ function parseMcpResponse(text, contentType, requestId) {
5051
+ if (!contentType?.toLowerCase().includes("text/event-stream")) {
5052
+ return JSON.parse(text);
5053
+ }
5054
+ for (const event of text.split(/\r?\n\r?\n/)) {
5055
+ const data = event.split(/\r?\n/).filter((line) => line.startsWith("data:")).map((line) => line.slice(5).replace(/^ /, "")).join("\n");
5056
+ if (!data.trim()) continue;
5057
+ const message = JSON.parse(data);
5058
+ if (message && typeof message === "object" && message.id === requestId) {
5059
+ return message;
5060
+ }
5061
+ }
5062
+ throw new Error(`MCP response stream did not contain a result for request "${requestId}".`);
5063
+ }
5049
5064
  function toOpenAiMessages(messages) {
5050
5065
  return [
5051
5066
  {
@@ -5443,6 +5458,16 @@ window.addEventListener("message", async (event) => {
5443
5458
  respond(event.source, message.id, { mode: message.params?.mode || "inline" });
5444
5459
  return;
5445
5460
  }
5461
+ if (message.method === "ui/notifications/size-changed") {
5462
+ const requestedHeight = Number(message.params?.height);
5463
+ const iframe = [...document.querySelectorAll(".tool-body iframe")]
5464
+ .find((candidate) => candidate.contentWindow === event.source);
5465
+ if (iframe && Number.isFinite(requestedHeight) && requestedHeight > 0) {
5466
+ iframe.style.height = Math.min(2000, Math.max(120, Math.ceil(requestedHeight))) + "px";
5467
+ iframe.dataset.autoSized = "true";
5468
+ }
5469
+ return;
5470
+ }
5446
5471
  if (message.method === "ui/message" || message.method === "ui/update-model-context") {
5447
5472
  respond(event.source, message.id, { isError: false });
5448
5473
  return;
@@ -5492,7 +5517,10 @@ async function streamChat(contentEl) {
5492
5517
  } else if (parsed.event === "tool_start") {
5493
5518
  appendToolStart(parsed.data);
5494
5519
  } else if (parsed.event === "tool_result") {
5495
- appendToolResult(parsed.data);
5520
+ const toolArticle = appendToolResult(parsed.data);
5521
+ if (parsed.data.tool?.resourceUri) {
5522
+ moveAssistantAfterToolUi(contentEl, toolArticle);
5523
+ }
5496
5524
  } else if (parsed.event === "error") {
5497
5525
  throw new Error(parsed.data.message || "Sidecar dev chat failed.");
5498
5526
  }
@@ -5562,6 +5590,17 @@ function renderAssistantError(element, message) {
5562
5590
  return text;
5563
5591
  }
5564
5592
 
5593
+ function moveAssistantAfterToolUi(contentEl, toolArticle) {
5594
+ const assistantArticle = contentEl.closest(".message");
5595
+ if (!assistantArticle || !toolArticle?.parentElement || assistantArticle === toolArticle) {
5596
+ return;
5597
+ }
5598
+ if (toolArticle.nextSibling === assistantArticle) {
5599
+ return;
5600
+ }
5601
+ messagesEl.insertBefore(assistantArticle, toolArticle.nextSibling);
5602
+ }
5603
+
5565
5604
  function appendToolStart(tool) {
5566
5605
  const article = document.createElement("article");
5567
5606
  article.className = "tool-card";
@@ -5569,6 +5608,7 @@ function appendToolStart(tool) {
5569
5608
  article.innerHTML = '<div class="tool-head"><div class="tool-title"></div><div class="status">Running</div></div><div class="tool-body"></div>';
5570
5609
  article.querySelector(".tool-title").textContent = tool.title || tool.name;
5571
5610
  messagesEl.append(article);
5611
+ return article;
5572
5612
  }
5573
5613
 
5574
5614
  function appendToolResult(event) {
@@ -5608,6 +5648,7 @@ function appendToolResult(event) {
5608
5648
  body.append(pre);
5609
5649
  }
5610
5650
  article.scrollIntoView({ block: "end" });
5651
+ return article;
5611
5652
  }
5612
5653
 
5613
5654
  function toolText(result) {