openmates 0.27.0-alpha.2 → 0.27.0-alpha.3

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.
@@ -60003,6 +60003,12 @@ Only output the final Markdown table. Do NOT include explanations, notes, or any
60003
60003
  title: {
60004
60004
  text: "Apps"
60005
60005
  },
60006
+ results: {
60007
+ text: "Results"
60008
+ },
60009
+ no_results: {
60010
+ text: "No results found."
60011
+ },
60006
60012
  app_label: {
60007
60013
  text: "App"
60008
60014
  },
@@ -83031,9 +83037,11 @@ var TuiTerminal = class {
83031
83037
  keyInput = new PassThrough();
83032
83038
  decoder = new StringDecoder("utf8");
83033
83039
  pendingInput = "";
83040
+ pendingMouse = "";
83034
83041
  paste = false;
83035
83042
  pasteText = "";
83036
83043
  inputTimer = null;
83044
+ mouseTimer = null;
83037
83045
  rawInput = (chunk) => this.receiveInput(typeof chunk === "string" ? chunk : this.decoder.write(chunk));
83038
83046
  input;
83039
83047
  output;
@@ -83069,6 +83077,7 @@ var TuiTerminal = class {
83069
83077
  this.output.write("\x1B[?1049h");
83070
83078
  this.output.write("\x1B[?25l");
83071
83079
  this.output.write("\x1B[?2004h");
83080
+ this.output.write("\x1B[?1000h\x1B[?1006h");
83072
83081
  this.output.write("\x1B[2J\x1B[H");
83073
83082
  }
83074
83083
  leave() {
@@ -83089,8 +83098,11 @@ var TuiTerminal = class {
83089
83098
  this.input.off("data", this.rawInput);
83090
83099
  if (this.resizeHandler) this.output.off("resize", this.resizeHandler);
83091
83100
  if (this.inputTimer) clearTimeout(this.inputTimer);
83101
+ if (this.mouseTimer) clearTimeout(this.mouseTimer);
83102
+ this.mouseTimer = null;
83092
83103
  this.inputTimer = null;
83093
83104
  this.pendingInput = "";
83105
+ this.pendingMouse = "";
83094
83106
  this.paste = false;
83095
83107
  this.pasteText = "";
83096
83108
  this.output.write("\x1B[?25h");
@@ -83114,6 +83126,7 @@ var TuiTerminal = class {
83114
83126
  this.output.write("\x1B[?1049h");
83115
83127
  this.output.write("\x1B[?25l");
83116
83128
  this.output.write("\x1B[?2004h");
83129
+ this.output.write("\x1B[?1000h\x1B[?1006h");
83117
83130
  this.output.write("\x1B[2J\x1B[H");
83118
83131
  }
83119
83132
  }
@@ -83130,9 +83143,10 @@ var TuiTerminal = class {
83130
83143
  }
83131
83144
  render(frame) {
83132
83145
  if (!this.active || this.suspended) return;
83133
- this.output.write("\x1B[H");
83134
- this.output.write(frame);
83135
- this.output.write("\x1B[J");
83146
+ const rows2 = frame.split("\n").slice(0, this.height);
83147
+ const body = rows2.map((row, index) => `\x1B[${index + 1};1H\x1B[2K${row}`).join("");
83148
+ const tail = rows2.length < this.height ? `\x1B[${rows2.length + 1};1H\x1B[J` : "";
83149
+ this.output.write(`\x1B[?2026h${body}${tail}\x1B[?2026l`);
83136
83150
  }
83137
83151
  receiveInput(text4) {
83138
83152
  if (this.inputTimer) clearTimeout(this.inputTimer);
@@ -83146,7 +83160,7 @@ var TuiTerminal = class {
83146
83160
  this.pasteText = (this.pasteText + before).slice(0, 131072);
83147
83161
  this.keyHandler?.(this.pasteText, { name: "paste" });
83148
83162
  this.pasteText = "";
83149
- } else this.keyInput.write(before);
83163
+ } else this.dispatchInput(before);
83150
83164
  this.paste = !this.paste;
83151
83165
  this.pendingInput = this.pendingInput.slice(found + marker.length);
83152
83166
  this.receiveInput("");
@@ -83157,13 +83171,53 @@ var TuiTerminal = class {
83157
83171
  const ready2 = this.pendingInput.slice(0, this.pendingInput.length - trailing);
83158
83172
  this.pendingInput = trailing ? this.pendingInput.slice(-trailing) : "";
83159
83173
  if (this.paste) this.pasteText = (this.pasteText + ready2).slice(0, 131072);
83160
- else if (ready2) this.keyInput.write(ready2);
83174
+ else if (ready2) this.dispatchInput(ready2);
83161
83175
  if (trailing && !this.paste) this.inputTimer = setTimeout(() => {
83162
- this.keyInput.write(this.pendingInput);
83176
+ this.dispatchInput(this.pendingInput);
83163
83177
  this.pendingInput = "";
83164
83178
  this.inputTimer = null;
83165
83179
  }, 30);
83166
83180
  }
83181
+ /** Consume SGR mouse reports without letting clicks become composer text. */
83182
+ dispatchInput(text4) {
83183
+ if (this.mouseTimer) clearTimeout(this.mouseTimer);
83184
+ this.mouseTimer = null;
83185
+ const input = this.pendingMouse + text4;
83186
+ this.pendingMouse = "";
83187
+ let offset = 0;
83188
+ while (offset < input.length) {
83189
+ const start = input.indexOf("\x1B[<", offset);
83190
+ if (start < 0) {
83191
+ const rest2 = input.slice(offset), prefix = rest2.endsWith("\x1B[") ? "\x1B[" : rest2.endsWith("\x1B") ? "\x1B" : "";
83192
+ this.keyInput.write(prefix ? rest2.slice(0, -prefix.length) : rest2);
83193
+ if (prefix) {
83194
+ this.pendingMouse = prefix;
83195
+ this.mouseTimer = setTimeout(() => {
83196
+ const pending = this.pendingMouse;
83197
+ this.pendingMouse = "";
83198
+ this.mouseTimer = null;
83199
+ if (pending === "\x1B") this.keyHandler?.("\x1B", { name: "escape", sequence: pending });
83200
+ else this.keyInput.write(pending);
83201
+ }, 500);
83202
+ }
83203
+ break;
83204
+ }
83205
+ this.keyInput.write(input.slice(offset, start));
83206
+ const rest = input.slice(start), report = /^\x1b\[<(\d+);(\d+);(\d+)([mM])/.exec(rest);
83207
+ if (!report) {
83208
+ if (rest.length < 128 && /^\x1b\[<[\d;]*$/.test(rest)) {
83209
+ this.pendingMouse = rest;
83210
+ break;
83211
+ }
83212
+ this.keyInput.write(rest.slice(0, 3));
83213
+ offset = start + 3;
83214
+ continue;
83215
+ }
83216
+ const button = Number(report[1]);
83217
+ if (report[4] === "M" && button & 64 && ((button & 3) === 0 || (button & 3) === 1)) this.keyHandler?.("", { name: (button & 3) === 0 ? "scrollup" : "scrolldown", sequence: report[0] });
83218
+ offset = start + report[0].length;
83219
+ }
83220
+ }
83167
83221
  removeListeners() {
83168
83222
  if (this.keyHandler) {
83169
83223
  this.keyInput.off("keypress", this.keyHandler);
@@ -83171,8 +83225,11 @@ var TuiTerminal = class {
83171
83225
  }
83172
83226
  this.input.off("data", this.rawInput);
83173
83227
  if (this.inputTimer) clearTimeout(this.inputTimer);
83228
+ if (this.mouseTimer) clearTimeout(this.mouseTimer);
83229
+ this.mouseTimer = null;
83174
83230
  this.inputTimer = null;
83175
83231
  this.pendingInput = "";
83232
+ this.pendingMouse = "";
83176
83233
  this.paste = false;
83177
83234
  this.pasteText = "";
83178
83235
  if (this.resizeHandler) {
@@ -83556,18 +83613,11 @@ function colorSequence(color, mode, background) {
83556
83613
  function foreground(value, color, mode, bold = false) {
83557
83614
  return mode === "none" ? value : `${bold ? "\x1B[1m" : ""}${colorSequence(rgb(color), mode, false)}${value}\x1B[0m`;
83558
83615
  }
83559
- function gradientLine(value, width, colors, mode, row = 0, rows2 = 1) {
83616
+ function backgroundLine(value, width, color, mode, bold = false) {
83560
83617
  const line = padCells(value, width);
83561
83618
  if (mode === "none") return line;
83562
- const start = rgb(colors.start), end = rgb(colors.end);
83563
- let output = mode === "ansi16" ? "\x1B[97m" : colorSequence([255, 255, 255], mode, false);
83564
- let column = 0;
83565
- for (const { segment } of segments.segment(line)) {
83566
- const ratio = (column / Math.max(1, width - 1) + row / Math.max(1, rows2 - 1)) / 2;
83567
- output += colorSequence(start.map((v, i) => Math.round(v + (end[i] - v) * ratio)), mode, true) + segment;
83568
- column += graphemeWidth(segment);
83569
- }
83570
- return output + "\x1B[0m";
83619
+ const white = mode === "ansi16" ? "\x1B[97m" : colorSequence([255, 255, 255], mode, false);
83620
+ return `${bold ? "\x1B[1m" : ""}${white}${colorSequence(rgb(color), mode, true)}${line}\x1B[0m`;
83571
83621
  }
83572
83622
 
83573
83623
  // src/tuiProjectsWorkspace.ts
@@ -84505,9 +84555,9 @@ function paletteActions(query) {
84505
84555
 
84506
84556
  // src/tuiLayout.ts
84507
84557
  var WORKSPACES = ["chats", "apps", "projects", "workflows", "tasks"];
84508
- var DEFAULT_CHAT_GRADIENT = { start: "#4867cd", end: "#5a85eb" };
84509
- function chatGradient(category) {
84510
- return category && CATEGORY_GRADIENTS[category] || DEFAULT_CHAT_GRADIENT;
84558
+ var DEFAULT_CHAT_BACKGROUND = "#4867cd";
84559
+ function chatBackground(category) {
84560
+ return category && CATEGORY_GRADIENTS[category]?.start || DEFAULT_CHAT_BACKGROUND;
84511
84561
  }
84512
84562
  function sidebarLines(state) {
84513
84563
  const selected = (label3, index) => `${state.focus === "sidebar" && state.sidebarIndex === index ? ">" : " "} ${label3}`;
@@ -84530,6 +84580,7 @@ function workspaceHint(state) {
84530
84580
  if (state.focus === "navigation") return "\u2190/\u2192 workspace Enter open Tab focus Ctrl+B sidebar";
84531
84581
  if (state.focus === "inspiration") return "\u2190/\u2192 inspiration Enter explore Tab focus";
84532
84582
  if (state.focus === "sidebar") return "\u2191/\u2193 choose Enter open Ctrl+B close Tab focus";
84583
+ if (state.screen === "start" || state.screen === "chats") return state.focus === "composer" ? "Enter send Shift+Tab chats Ctrl+N new Ctrl+B sidebar" : "\u2190/\u2192 chat Enter open Tab write \u2191/\u2193 scroll Ctrl+B sidebar";
84533
84584
  if (state.workflowEdit) return "Enter save title Esc cancel edit";
84534
84585
  if (state.screen === "workflow") return "g template r runs \u2191/\u2193 select Enter expand e title E config x run c cancel";
84535
84586
  if (state.screen === "task") return "e edit m status a activity s start d done b block Esc back";
@@ -84538,7 +84589,7 @@ function workspaceHint(state) {
84538
84589
  if (state.screen === "app-skill") return "1\u20133 tabs Enter use skill Esc app Ctrl+P actions";
84539
84590
  if (state.screen === "app-result") return "\u2191/\u2193 scroll Esc saved results Ctrl+P actions";
84540
84591
  if (state.screen === "apps") return "\u2191/\u2193 choose Enter open /search /browse Show all Tab focus";
84541
- if (state.screen === "projects" || state.screen === "tasks" || state.screen === "workflows" || state.screen === "chats") return "\u2191/\u2193 choose Enter open /search filter Tab focus Ctrl+P actions";
84592
+ if (state.screen === "projects" || state.screen === "tasks" || state.screen === "workflows") return "\u2191/\u2193 choose Enter open /search filter Tab focus Ctrl+P actions";
84542
84593
  if (state.screen === "interests") return "\u2191/\u2193 move Space select Enter continue Esc back";
84543
84594
  if (state.screen === "examples") return "\u2191/\u2193 choose Enter open /search filter Esc back";
84544
84595
  return "Enter send Alt+Enter newline Ctrl+B sidebar Ctrl+P actions @ attach";
@@ -84598,20 +84649,22 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
84598
84649
  if (overlay) {
84599
84650
  const marker = content.findIndex((row) => lineText(row).startsWith("> "));
84600
84651
  start = marker >= bodyHeight ? Math.max(0, marker - bodyHeight + 3) : 0;
84601
- } else if (["start", "tasks", "projects", "project", "chats", "examples", "workflow", "workflows", "apps", "app", "app-skill"].includes(state.screen) && state.focus === "content") {
84652
+ } else if (state.followSelection && ["start", "tasks", "projects", "project", "chats", "examples", "workflow", "workflows", "apps", "app", "app-skill"].includes(state.screen) && state.focus === "content") {
84602
84653
  const markers = content.map((row, index) => /(?:^|[│|])\s*[>›] /.test(lineText(row)) ? index : -1).filter((index) => index >= 0);
84603
84654
  const marker = state.screen === "workflow" ? markers.at(-1) ?? -1 : markers[0] ?? -1;
84604
84655
  let selectionEnd = marker;
84605
- if (state.screen === "workflow" && marker >= 0) {
84656
+ if (["workflow", "start", "chats"].includes(state.screen) && marker >= 0) {
84606
84657
  const closing = content.findIndex((row, index) => index > marker && lineText(row).includes("\u2570"));
84607
84658
  selectionEnd = Math.min(marker + 10, closing < 0 ? marker : closing);
84608
84659
  }
84609
- if (selectionEnd >= start + viewportHeight) start = Math.min(maxStart, selectionEnd - viewportHeight + 2);
84660
+ if (selectionEnd >= start + viewportHeight) start = Math.min(maxStart, selectionEnd - viewportHeight + 1);
84610
84661
  if (marker >= 0 && marker < start) start = marker;
84611
84662
  }
84663
+ if (!overlay && !sidebarOverlay) state.scrollOffset = state.screen === "chat" ? maxStart - start : start;
84664
+ state.followSelection = false;
84612
84665
  const heroRows = options.headerRows ?? 0;
84613
84666
  const category = state.screen === "example" ? state.activeExample?.chat.category : state.activeChat?.category;
84614
- const gradient = chatGradient(category);
84667
+ const background = chatBackground(category);
84615
84668
  const allSide = sidebarLines(state);
84616
84669
  const sideMarker = allSide.findIndex((row) => row.startsWith("> "));
84617
84670
  const sideStart = Math.max(0, sideMarker - bodyHeight + 3);
@@ -84626,8 +84679,18 @@ function renderWorkspaceFrame(state, rawWidth, rawHeight, body, options = {}) {
84626
84679
  if (style && !overlay && !sidebarOverlay) {
84627
84680
  const inset = Math.max(0, Math.min(Math.floor(contentWidth / 2) - 1, style.inset ?? 0));
84628
84681
  const span = Math.max(1, contentWidth - 2 * inset);
84629
- rendered = " ".repeat(inset) + (style.gradient ? gradientLine(raw, span, style.gradient, mode, style.row ?? 0, style.rows ?? 1) : foreground(padCells(raw, span), style.color ?? "#e6e6e6", mode, style.bold)) + " ".repeat(inset);
84630
- } else if (!overlay && !sidebarOverlay && index < heroRows) rendered = gradientLine(raw, contentWidth, gradient, mode, index, heroRows);
84682
+ if (style.spans) {
84683
+ let remaining = span;
84684
+ rendered = "";
84685
+ for (const part of style.spans) {
84686
+ const text4 = truncateCells(terminalText(part.text).replace(/\n/g, " "), remaining), size = cells(text4);
84687
+ rendered += part.background ? backgroundLine(text4, size, part.background, mode, part.bold) : text4;
84688
+ remaining -= size;
84689
+ if (!remaining) break;
84690
+ }
84691
+ rendered = " ".repeat(inset) + rendered + " ".repeat(remaining + inset);
84692
+ } else rendered = " ".repeat(inset) + (style.background ? backgroundLine(raw, span, style.background, mode, style.bold) : foreground(padCells(raw, span), style.color ?? "#e6e6e6", mode, style.bold)) + " ".repeat(inset);
84693
+ } else if (!overlay && !sidebarOverlay && index < heroRows) rendered = backgroundLine(raw, contentWidth, background, mode);
84631
84694
  else if (raw.startsWith("> ") || raw.includes("\u203A")) rendered = foreground(rendered, "#ff553b", mode, true);
84632
84695
  else if (/^(You|Sophia|Tasks|Projects|Workflows|Recent chats|Suggestions|Actions)$/.test(raw)) rendered = foreground(rendered, "#5a85eb", mode, true);
84633
84696
  if (sidebarWidth) rendered = foreground(padCells(side[i] ?? "", sidebarWidth - 2), "#cfcfcf", mode) + `${vertical} ` + rendered;
@@ -84916,31 +84979,61 @@ function homeHeader(state, width, height) {
84916
84979
  const title = inspiration?.feature?.title || inspiration?.title || "Daily inspiration";
84917
84980
  const banner = [centered2(`DAILY INSPIRATION ${state.focus === "inspiration" ? "\u2039 Enter open \u203A" : "\u2039 Ctrl+O explore \u203A"}`, width), "", ...parts.map((line) => centered2(line, width)), centered2(title, width)];
84918
84981
  while (banner.length < rows2) banner.push("");
84919
- banner.forEach((text4, row) => result.push({ text: text4, gradient, row, rows: banner.length }));
84982
+ banner.forEach((text4) => result.push({ text: text4, background: gradient.start }));
84920
84983
  result.push("", { text: centered2(state.workspace === "apps" ? prompts.apps : state.username ? `Hey ${state.username}!` : "Hey there!", width), bold: true });
84921
84984
  if (state.workspace !== "chats" || !homeChatItems(state).length) result.push({ text: centered2(state.workspace === "apps" ? "Use your apps directly and return to saved results." : prompts[state.workspace], width), color: "#cfcfcf" });
84922
84985
  result.push("");
84923
84986
  return result;
84924
84987
  }
84925
84988
  function renderHomeChatCards(state, width, height) {
84926
- const all = homeChatItems(state), chats = state.homeShowAll || state.filter ? all : all.slice(0, Math.max(3, state.selectedIndex + 1));
84927
- const result = homeHeader(state, width, height);
84928
- if (chats.length) result.push(centered2(state.signedIn ? "Continue where you left off" : "Explore example chats", width), "");
84929
- else result.push(centered2(state.homeLoading ? "Loading your recent chats\u2026" : "Start a chat below. Your recent chats will appear here.", width), "");
84930
- const cardWidth = Math.min(width, 88), inset = Math.max(0, Math.floor((width - cardWidth) / 2)), inner = Math.max(1, cardWidth - 4);
84931
- chats.forEach((chat, index) => {
84932
- const gradient = chat.category && CATEGORY_GRADIENTS[chat.category] || BLUE;
84989
+ const chats = homeChatItems(state), result = homeHeader(state, width, height);
84990
+ if (!chats.length) {
84991
+ result.push(centered2(state.homeLoading ? "Loading your recent chats\u2026" : "Start a chat below. Your recent chats will appear here.", width), "");
84992
+ return result;
84993
+ }
84994
+ result.push(centered2(state.signedIn ? "Continue where you left off" : "Explore example chats", width), "");
84995
+ const selected = Math.max(0, Math.min(chats.length - 1, state.selectedIndex));
84996
+ const cardWidth = Math.min(width, 36), inner = Math.max(1, cardWidth - 4), stride = cardWidth + 2;
84997
+ const slots = Math.max(1, Math.floor((width + 2) / stride));
84998
+ const first = Math.max(0, selected - slots + 1);
84999
+ const cards = chats.slice(first, first + slots + 1).map((chat, index) => {
85000
+ const active = first + index === selected && state.focus === "content";
85001
+ const title = wrapCells(`${active ? "\u203A " : ""}${chat.title || "Untitled chat"}`, inner).slice(0, 2);
85002
+ const summary = wrapCells(chat.summary || "Continue this conversation", inner).slice(0, 2);
85003
+ while (title.length < 2) title.push("");
85004
+ while (summary.length < 2) summary.push("");
84933
85005
  const rows2 = cardWidth < 4 ? [truncateCells(chat.title || "Untitled chat", cardWidth)] : [
84934
- `\u256D${"\u2500".repeat(Math.max(0, cardWidth - 2))}\u256E`,
84935
- `\u2502 ${padCells(`${index === state.selectedIndex && state.focus === "content" ? "\u203A" : " "} ${chat.title || "Untitled chat"}`, inner)} \u2502`,
84936
- `\u2502 ${padCells(chat.summary || "Continue this conversation", inner)} \u2502`,
85006
+ `\u256D${"\u2500".repeat(cardWidth - 2)}\u256E`,
85007
+ ...title.map((line) => `\u2502 ${padCells(line, inner)} \u2502`),
85008
+ ...summary.map((line) => `\u2502 ${padCells(line, inner)} \u2502`),
84937
85009
  `\u2502 ${padCells(chat.category?.replaceAll("_", " ") || "Chat", inner)} \u2502`,
84938
- `\u2570${"\u2500".repeat(Math.max(0, cardWidth - 2))}\u256F`
85010
+ `\u2570${"\u2500".repeat(cardWidth - 2)}\u256F`
84939
85011
  ];
84940
- rows2.forEach((text4, row) => result.push({ text: text4, gradient, inset, row, rows: rows2.length }));
84941
- result.push("");
85012
+ return { rows: rows2, background: (chat.category && CATEGORY_GRADIENTS[chat.category] || BLUE).start, active };
84942
85013
  });
84943
- result.push(centered2(`${state.homeShowAll ? "Back to recent" : "Show my chats"} \xB7 Search \xB7 /new New chat`, width));
85014
+ for (let row = 0; row < cards[0].rows.length; row++) {
85015
+ const spans = [];
85016
+ let remaining = width;
85017
+ for (const card of cards) {
85018
+ if (!remaining) break;
85019
+ const text4 = truncateCells(card.rows[row], remaining);
85020
+ spans.push({ text: text4, background: card.background, bold: card.active });
85021
+ remaining -= cells(text4);
85022
+ if (remaining) {
85023
+ const gap = " ".repeat(Math.min(2, remaining));
85024
+ spans.push({ text: gap });
85025
+ remaining -= gap.length;
85026
+ }
85027
+ }
85028
+ result.push({ text: spans.map((span) => span.text).join(""), spans });
85029
+ }
85030
+ result.push(
85031
+ "",
85032
+ centered2(`${selected > 0 ? "\u2039" : " "} Chat ${selected + 1} of ${chats.length} ${selected < chats.length - 1 ? "\u203A" : " "}`, width),
85033
+ centered2("\u2190/\u2192 choose chat \xB7 Enter open \xB7 Tab write", width),
85034
+ "",
85035
+ centered2("/search Search chats \xB7 Ctrl+N New chat", width)
85036
+ );
84944
85037
  return result;
84945
85038
  }
84946
85039
 
@@ -85677,7 +85770,7 @@ function createInitialTuiState() {
85677
85770
  sidebarOpen: false,
85678
85771
  sidebarIndex: 0,
85679
85772
  navigationIndex: 0,
85680
- focus: "composer",
85773
+ focus: "content",
85681
85774
  signedIn: false,
85682
85775
  form: null,
85683
85776
  paletteOpen: false,
@@ -85711,6 +85804,7 @@ function createInitialTuiState() {
85711
85804
  screen: "start",
85712
85805
  input: "",
85713
85806
  scrollOffset: 0,
85807
+ followSelection: false,
85714
85808
  selectedIndex: 0,
85715
85809
  selectedInterests: [],
85716
85810
  examples: [],
@@ -85780,7 +85874,7 @@ function renderTuiFrame(state, width, height, options = {}) {
85780
85874
  return renderWorkspaceFrame(state, width, height, renderBody(state, bodyWidth, height), { ...options, stickyRows, headerRows: state.screen === "chat" || state.screen === "example" ? renderChatHeader(state, bodyWidth).length : void 0 });
85781
85875
  }
85782
85876
  function coloredHero(lines, rows2, gradient = PRIMARY_GRADIENT) {
85783
- return lines.map((text4, index) => index < rows2 ? { text: text4, gradient, row: index, rows: rows2 } : text4);
85877
+ return lines.map((text4, index) => index < rows2 ? { text: text4, background: gradient.start } : text4);
85784
85878
  }
85785
85879
  var blueHero = (lines, rows2) => coloredHero(lines, rows2);
85786
85880
  function homeCards(lines, width, gradients) {
@@ -85792,7 +85886,7 @@ function homeCards(lines, width, gradients) {
85792
85886
  }
85793
85887
  return groups.filter((group) => group.length).flatMap((group, index) => {
85794
85888
  const cardWidth = Math.min(width, Math.max(...group.map(cells))), inset = Math.max(0, Math.floor((width - cardWidth) / 2));
85795
- return [...group.map((text4, row) => ({ text: text4, gradient: gradients[index] ?? PRIMARY_GRADIENT, inset, row, rows: group.length })), ""];
85889
+ return [...group.map((text4) => ({ text: text4, background: (gradients[index] ?? PRIMARY_GRADIENT).start, inset })), ""];
85796
85890
  });
85797
85891
  }
85798
85892
  function renderBody(state, width, height) {
@@ -86107,7 +86201,7 @@ function route(state, workspace, screen) {
86107
86201
  state.workspace = workspace;
86108
86202
  state.screen = screen;
86109
86203
  state.navigationIndex = WORKSPACES.indexOf(workspace);
86110
- state.focus = workspace === "chats" && screen !== "chats" ? "composer" : "content";
86204
+ state.focus = workspace === "chats" && !["start", "chats"].includes(screen) ? "composer" : "content";
86111
86205
  state.input = "";
86112
86206
  state.inputCursor = null;
86113
86207
  state.filter = "";
@@ -86342,7 +86436,7 @@ async function handleWorkspaceCommand(context, command) {
86342
86436
  return true;
86343
86437
  case "/sidebar":
86344
86438
  state.sidebarOpen = !state.sidebarOpen;
86345
- state.focus = state.sidebarOpen ? "sidebar" : state.workspace === "chats" ? "composer" : "content";
86439
+ state.focus = state.sidebarOpen ? "sidebar" : state.workspace === "chats" && !["start", "chats"].includes(state.screen) ? "composer" : "content";
86346
86440
  render();
86347
86441
  if (state.sidebarOpen) await recent(context);
86348
86442
  return true;
@@ -86672,18 +86766,24 @@ async function handleWorkspaceKey(context, chunk, key) {
86672
86766
  return true;
86673
86767
  }
86674
86768
  if (state.workflowEdit) return false;
86675
- if (["pageup", "pagedown", "home", "end"].includes(key.name ?? "")) {
86769
+ const chatHome = state.screen === "start" || state.screen === "chats";
86770
+ if (["pageup", "pagedown", "home", "end", "scrollup", "scrolldown"].includes(key.name ?? "") || (chatHome || state.screen === "project" && state.projectTab === "overview") && ["up", "down"].includes(key.name ?? "") && ["composer", "content"].includes(state.focus) && !state.input.startsWith("/")) {
86676
86771
  const bottom = state.screen === "chat";
86772
+ state.followSelection = false;
86677
86773
  if (key.name === "home") state.scrollOffset = bottom ? 1e4 : 0;
86678
86774
  else if (key.name === "end") state.scrollOffset = bottom ? 0 : 1e4;
86679
- else state.scrollOffset = Math.max(0, state.scrollOffset + (key.name === "pageup" ? -1 : 1) * (bottom ? -10 : 10));
86775
+ else {
86776
+ const direction = ["pageup", "scrollup", "up"].includes(key.name ?? "") ? -1 : 1;
86777
+ const step = key.name?.startsWith("page") ? Math.max(1, (context.terminal.height ?? 24) - 9) : key.name?.startsWith("scroll") ? 3 : 1;
86778
+ state.scrollOffset = Math.max(0, state.scrollOffset + direction * (bottom ? -step : step));
86779
+ }
86680
86780
  render();
86681
86781
  return true;
86682
86782
  }
86683
86783
  if (key.name === "escape") {
86684
86784
  if (state.focus === "sidebar") {
86685
86785
  state.sidebarOpen = false;
86686
- state.focus = state.workspace === "chats" ? "composer" : "content";
86786
+ state.focus = chatHome ? "content" : state.workspace === "chats" ? "composer" : "content";
86687
86787
  } else if (state.screen === "task") {
86688
86788
  state.screen = state.workspace === "projects" ? "project" : "tasks";
86689
86789
  state.focus = "content";
@@ -86726,7 +86826,7 @@ async function handleWorkspaceKey(context, chunk, key) {
86726
86826
  const choices = TUI_ACTIONS.filter((a) => a.command.startsWith(state.input));
86727
86827
  if (choices.length) state.input = choices[state.paletteIndex % choices.length].command + " ";
86728
86828
  } else {
86729
- const focuses = ["composer", ...isWorkspaceHome(state) ? ["inspiration"] : [], "content", ...state.sidebarOpen ? ["sidebar"] : [], "navigation"];
86829
+ const focuses = ["content", "composer", ...isWorkspaceHome(state) ? ["inspiration"] : [], ...state.sidebarOpen ? ["sidebar"] : [], "navigation"];
86730
86830
  state.focus = focuses[(focuses.indexOf(state.focus) + (key.shift ? -1 : 1) + focuses.length) % focuses.length];
86731
86831
  }
86732
86832
  render();
@@ -86740,6 +86840,14 @@ async function handleWorkspaceKey(context, chunk, key) {
86740
86840
  render();
86741
86841
  return true;
86742
86842
  }
86843
+ if (chatHome && state.focus === "content" && (key.name === "left" || key.name === "right")) {
86844
+ state.selectedIndex = Math.max(0, Math.min(Math.max(0, homeChatItems(state).length - 1), state.selectedIndex + (key.name === "left" ? -1 : 1)));
86845
+ state.followSelection = true;
86846
+ render();
86847
+ return true;
86848
+ }
86849
+ if (chatHome && state.focus === "content" && !key.ctrl && !key.meta && chunk && chunk >= " " && key.name !== "return") state.focus = "composer";
86850
+ if (state.focus === "content" && (["up", "down", "return"].includes(key.name ?? "") || state.screen === "workflow" && ["g", "r", "e", "E", "x", "c"].includes(chunk))) state.followSelection = true;
86743
86851
  if (state.focus === "navigation") {
86744
86852
  if (key.name === "left" || key.name === "right") state.navigationIndex = (state.navigationIndex + (key.name === "left" ? -1 : 1) + WORKSPACES.length) % WORKSPACES.length;
86745
86853
  else if (key.name === "return") await context.command(`/${WORKSPACES[state.navigationIndex]}`);
@@ -87607,7 +87715,7 @@ async function moveSelectionOrScroll(params, direction) {
87607
87715
  state.selectedWorkflowNodeIndex = clamp(state.selectedWorkflowNodeIndex + direction, 0, Math.max(0, nodeCount - 1));
87608
87716
  return;
87609
87717
  }
87610
- state.scrollOffset = Math.max(0, state.scrollOffset - direction);
87718
+ state.scrollOffset = Math.max(0, state.scrollOffset + direction * (state.screen === "chat" ? -1 : 1));
87611
87719
  }
87612
87720
  function toggleSelectedWorkflowNode(state) {
87613
87721
  const workflow = state.activeWorkflow;
package/dist/cli.js CHANGED
@@ -19,7 +19,7 @@ import {
19
19
  serializeToYaml,
20
20
  shouldRequireTrustedAccountGuard,
21
21
  waitForWorkflowRun
22
- } from "./chunk-S7KAERLW.js";
22
+ } from "./chunk-USV2GHLA.js";
23
23
  import "./chunk-IWKP55ZB.js";
24
24
  import "./chunk-BBKJZ23O.js";
25
25
  export {
package/dist/index.js CHANGED
@@ -43,7 +43,7 @@ import {
43
43
  selectAssistantMessagesForSpeech,
44
44
  serializeToYaml,
45
45
  summarizeAssistantSpeech
46
- } from "./chunk-S7KAERLW.js";
46
+ } from "./chunk-USV2GHLA.js";
47
47
  import "./chunk-IWKP55ZB.js";
48
48
  import "./chunk-BBKJZ23O.js";
49
49
  export {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openmates",
3
- "version": "0.27.0-alpha.2",
3
+ "version": "0.27.0-alpha.3",
4
4
  "description": "OpenMates CLI and SDK",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",