omnius 1.0.885 → 1.0.888

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.
@@ -179,6 +179,27 @@ function nativeTextFromAnsi(value) {
179
179
  }
180
180
 
181
181
  // packages/cli/src/tui/native/components/text.ts
182
+ var colorCache = /* @__PURE__ */ new Map();
183
+ function nativeColor(value, background2 = false) {
184
+ if (value === void 0 || value === -1 || value === "default")
185
+ return background2 ? RGBA.defaultBackground() : RGBA.defaultForeground();
186
+ const key = String(value);
187
+ if (key === "index:-1") return background2 ? RGBA.defaultBackground() : RGBA.defaultForeground();
188
+ let color = colorCache.get(key);
189
+ if (!color) {
190
+ const index = typeof value === "number" || /^\d+$/.test(key) ? Number(value) : key.startsWith("index:") ? Number(key.slice(6)) : void 0;
191
+ if (index !== void 0 ? !Number.isInteger(index) || index < 0 || index > 255 : !/^#?(?:[\da-f]{3}|[\da-f]{4}|[\da-f]{6}|[\da-f]{8})$/i.test(key))
192
+ return background2 ? RGBA.defaultBackground() : RGBA.defaultForeground();
193
+ try {
194
+ color = index === void 0 ? RGBA.fromHex(key) : RGBA.fromIndex(index);
195
+ } catch {
196
+ return background2 ? RGBA.defaultBackground() : RGBA.defaultForeground();
197
+ }
198
+ if (colorCache.size >= 1024) colorCache.delete(colorCache.keys().next().value);
199
+ colorCache.set(key, color);
200
+ }
201
+ return color;
202
+ }
182
203
  function plainText(value) {
183
204
  return typeof value === "string" ? stripTextControls(value) : (value ?? []).map((span) => stripTextControls(span.text)).join("");
184
205
  }
@@ -189,6 +210,7 @@ function styledText(value) {
189
210
  return new StyledText(textSpans(value).map((span) => ({
190
211
  __isChunk: true,
191
212
  text: span.text,
213
+ ...span.fg === void 0 ? {} : { fg: nativeColor(span.fg) },
192
214
  ...span.attributes === void 0 ? {} : { attributes: span.attributes },
193
215
  ...span.link ? { link: { url: span.link } } : {}
194
216
  })));
@@ -1653,6 +1675,16 @@ var NativeBlockView = class {
1653
1675
  get block() {
1654
1676
  return this.spec;
1655
1677
  }
1678
+ get trailingSpace() {
1679
+ return this.spec.kind === "markdown" && this.spec.presentation === "final-answer" ? 1 : 0;
1680
+ }
1681
+ get hasVisibleContent() {
1682
+ return this.spec.kind !== "column" && this.spec.kind !== "row" || Boolean(this.spec.title || this.spec.text !== void 0 || this.spec.actions?.length || [...this.children?.views.values() ?? []].some((view) => view.hasVisibleContent));
1683
+ }
1684
+ setTurnSeparation(separate, previousBottom = 0) {
1685
+ const answer = this.spec.kind === "markdown" && this.spec.presentation === "final-answer";
1686
+ this.root.marginTop = separate ? Math.max(0, 1 - previousBottom) : answer ? 1 : 0;
1687
+ }
1656
1688
  build() {
1657
1689
  const { renderer: renderer2, colors, syntax } = this.context;
1658
1690
  const spec = this.spec;
@@ -1951,12 +1983,13 @@ var NativeBlockView = class {
1951
1983
  }
1952
1984
  applyTheme() {
1953
1985
  const colors = this.context.colors;
1986
+ const heading = this.spec.color === void 0 ? colors.foreground : nativeColor(this.spec.color);
1954
1987
  this.root.backgroundColor = colors.background;
1955
1988
  this.root.shouldFill = this.spec.kind !== "model3d";
1956
- if (this.spec.kind === "card") this.root.borderColor = colors.border;
1989
+ if (this.spec.kind === "card") this.root.borderColor = this.spec.color === void 0 ? colors.border : heading;
1957
1990
  else this.root.border = false;
1958
1991
  if (this.title) {
1959
- this.title.fg = colors.foreground;
1992
+ this.title.fg = heading;
1960
1993
  this.title.bg = colors.background;
1961
1994
  }
1962
1995
  if (this.body) {
@@ -1964,11 +1997,11 @@ var NativeBlockView = class {
1964
1997
  this.body.shouldFill = this.spec.kind !== "model3d";
1965
1998
  }
1966
1999
  if (this.text) {
1967
- this.text.fg = colors.foreground;
2000
+ this.text.fg = this.spec.kind === "text" || this.spec.kind === "progress" ? heading : colors.foreground;
1968
2001
  this.text.bg = colors.background;
1969
2002
  }
1970
2003
  if (this.progress) {
1971
- this.progress.fg = colors.foreground;
2004
+ this.progress.fg = this.spec.color === void 0 ? colors.accent : heading;
1972
2005
  this.progress.bg = colors.background;
1973
2006
  }
1974
2007
  for (const action of this.actions?.getChildren() ?? []) if (action instanceof TextRenderable3) {
@@ -1998,12 +2031,14 @@ var NativeBlockView = class {
1998
2031
  }
1999
2032
  };
2000
2033
  var NativeBlockList = class {
2001
- constructor(context, parent) {
2034
+ constructor(context, parent, separateTurns = false) {
2002
2035
  this.context = context;
2003
2036
  this.parent = parent;
2037
+ this.separateTurns = separateTurns;
2004
2038
  }
2005
2039
  context;
2006
2040
  parent;
2041
+ separateTurns;
2007
2042
  views = /* @__PURE__ */ new Map();
2008
2043
  order = [];
2009
2044
  patch(patch) {
@@ -2021,6 +2056,20 @@ var NativeBlockList = class {
2021
2056
  }
2022
2057
  }
2023
2058
  if (patch.order) this.reorder(patch.order);
2059
+ if (this.separateTurns) {
2060
+ let turnId, previousBottom = 0;
2061
+ for (const id of this.order) {
2062
+ const view = this.views.get(id);
2063
+ if (!view.hasVisibleContent) {
2064
+ view.setTurnSeparation(false);
2065
+ continue;
2066
+ }
2067
+ const nextTurn = view.block.turnId;
2068
+ view.setTurnSeparation(Boolean(turnId && nextTurn && turnId !== nextTurn), previousBottom);
2069
+ if (nextTurn) turnId = nextTurn;
2070
+ previousBottom = view.trailingSpace;
2071
+ }
2072
+ }
2024
2073
  }
2025
2074
  replace(blocks) {
2026
2075
  const keep = new Set(blocks.map((block) => block.id));
@@ -7671,7 +7720,7 @@ var NativeTabStrip = class extends BoxRenderable11 {
7671
7720
  },
7672
7721
  onKeyDown: (key) => this.handleKey(entry, key)
7673
7722
  });
7674
- entry = { action, active: false, blocked: false, button };
7723
+ entry = { action, active: false, blocked: false, closeBlocked: false, button };
7675
7724
  this.buttons.set(action.id, entry);
7676
7725
  button.on("focused", () => {
7677
7726
  this.style(entry);
@@ -7691,7 +7740,7 @@ var NativeTabStrip = class extends BoxRenderable11 {
7691
7740
  fg: this.colors.foreground,
7692
7741
  bg: this.colors.background,
7693
7742
  onMouseDown: (event) => {
7694
- if (event.button === 0 && !entry.blocked) {
7743
+ if (event.button === 0 && !entry.closeBlocked) {
7695
7744
  close2.focus();
7696
7745
  this.options.close(entry.action.id);
7697
7746
  }
@@ -7712,8 +7761,9 @@ var NativeTabStrip = class extends BoxRenderable11 {
7712
7761
  entry.action = action;
7713
7762
  entry.active = action.id === activeId;
7714
7763
  entry.blocked = busy || Boolean(action.disabled);
7764
+ entry.closeBlocked = entry.blocked || Boolean(action.closeDisabled);
7715
7765
  entry.button.focusable = entry.active || !entry.blocked;
7716
- if (entry.close) entry.close.focusable = !entry.blocked;
7766
+ if (entry.close) entry.close.focusable = !entry.closeBlocked;
7717
7767
  const label3 = plainText(action.label);
7718
7768
  const content = ` ${label3} `;
7719
7769
  if (entry.button.plainText !== content) entry.button.content = content;
@@ -7731,17 +7781,17 @@ var NativeTabStrip = class extends BoxRenderable11 {
7731
7781
  }
7732
7782
  style(entry) {
7733
7783
  entry.button.attributes = (entry.active ? TextAttributes10.BOLD | TextAttributes10.UNDERLINE : entry.blocked ? TextAttributes10.DIM : 0) | (entry.button.focused ? TextAttributes10.INVERSE : 0);
7734
- if (entry.close) entry.close.attributes = (entry.blocked || !entry.close.focused ? TextAttributes10.DIM : 0) | (entry.close.focused ? TextAttributes10.INVERSE : 0);
7784
+ if (entry.close) entry.close.attributes = (entry.closeBlocked || !entry.close.focused ? TextAttributes10.DIM : 0) | (entry.close.focused ? TextAttributes10.INVERSE : 0);
7735
7785
  }
7736
7786
  handleKey(entry, key, close2 = false) {
7737
7787
  if (key.eventType === "release") return;
7738
7788
  if (key.name === "return" || key.sequence === " ") {
7739
- if (!entry.blocked) {
7789
+ if (close2 ? !entry.closeBlocked : !entry.blocked) {
7740
7790
  if (close2) this.options.close?.(entry.action.id);
7741
7791
  else this.options.activate(entry.action.id);
7742
7792
  }
7743
7793
  } else if (this.options.close && (key.name === "delete" || key.ctrl && key.name.toLowerCase() === "w")) {
7744
- if (!entry.blocked) this.options.close(entry.action.id);
7794
+ if (!entry.closeBlocked) this.options.close(entry.action.id);
7745
7795
  } else if (["left", "right", "home", "end"].includes(key.name)) {
7746
7796
  const targets = this.scroll.getChildren().filter((button) => button.focusable && button.id.startsWith(`${this.options.prefix}:`));
7747
7797
  const index = targets.indexOf(entry.button);
@@ -7975,13 +8025,13 @@ var NativeFrontend = class {
7975
8025
  fg: colors.foreground,
7976
8026
  bg: colors.background,
7977
8027
  onMouseDown: (event) => {
7978
- if (event.button === 0 && !this.state?.sessions?.busy) this.emitAction("session-new");
8028
+ if (event.button === 0) this.emitAction("session-new");
7979
8029
  event.preventDefault();
7980
8030
  event.stopPropagation();
7981
8031
  },
7982
8032
  onKeyDown: (key) => {
7983
8033
  if (key.eventType !== "release" && (key.name === "return" || key.sequence === " ")) {
7984
- if (!this.state?.sessions?.busy) this.emitAction("session-new");
8034
+ this.emitAction("session-new");
7985
8035
  key.preventDefault();
7986
8036
  key.stopPropagation();
7987
8037
  }
@@ -7989,7 +8039,7 @@ var NativeFrontend = class {
7989
8039
  });
7990
8040
  this.newSession.focusable = true;
7991
8041
  const styleNew = () => {
7992
- this.newSession.attributes = (this.state?.sessions?.busy ? TextAttributes11.DIM : 0) | (this.newSession.focused ? TextAttributes11.INVERSE : 0);
8042
+ this.newSession.attributes = this.newSession.focused ? TextAttributes11.INVERSE : 0;
7993
8043
  };
7994
8044
  this.newSession.on("focused", styleNew);
7995
8045
  this.newSession.on("blurred", styleNew);
@@ -8004,13 +8054,13 @@ var NativeFrontend = class {
8004
8054
  fg: colors.foreground,
8005
8055
  bg: colors.background,
8006
8056
  onMouseDown: (event) => {
8007
- if (event.button === 0 && !this.state?.sessions?.busy) this.emitAction("session-picker");
8057
+ if (event.button === 0) this.emitAction("session-picker");
8008
8058
  event.preventDefault();
8009
8059
  event.stopPropagation();
8010
8060
  },
8011
8061
  onKeyDown: (key) => {
8012
8062
  if (key.eventType !== "release" && (key.name === "return" || key.sequence === " ")) {
8013
- if (!this.state?.sessions?.busy) this.emitAction("session-picker");
8063
+ this.emitAction("session-picker");
8014
8064
  key.preventDefault();
8015
8065
  key.stopPropagation();
8016
8066
  }
@@ -8018,7 +8068,7 @@ var NativeFrontend = class {
8018
8068
  });
8019
8069
  this.sessionPicker.focusable = true;
8020
8070
  const stylePicker = () => {
8021
- this.sessionPicker.attributes = (this.state?.sessions?.busy ? TextAttributes11.DIM : 0) | (this.sessionPicker.focused ? TextAttributes11.INVERSE : 0);
8071
+ this.sessionPicker.attributes = this.sessionPicker.focused ? TextAttributes11.INVERSE : 0;
8022
8072
  };
8023
8073
  this.sessionPicker.on("focused", stylePicker);
8024
8074
  this.sessionPicker.on("blurred", stylePicker);
@@ -8096,7 +8146,7 @@ var NativeFrontend = class {
8096
8146
  } }
8097
8147
  });
8098
8148
  this.transcriptPane.add(this.scroll);
8099
- this.content = new NativeBlockList(this.context, this.scroll);
8149
+ this.content = new NativeBlockList(this.context, this.scroll, true);
8100
8150
  this.instrumentDivider = new InstrumentDivider(renderer2, {
8101
8151
  resize: (column3) => this.resizeInstruments(column3),
8102
8152
  toggle: () => this.toggleDetails(),
@@ -8392,6 +8442,7 @@ var NativeFrontend = class {
8392
8442
  history = [];
8393
8443
  historyIndex = -1;
8394
8444
  savedInput = "";
8445
+ savedInputCursor = 0;
8395
8446
  disposeSelectionContrast;
8396
8447
  actionSignatures = /* @__PURE__ */ new WeakMap();
8397
8448
  detailsOpen;
@@ -8416,6 +8467,7 @@ var NativeFrontend = class {
8416
8467
  const previousView = this.state ? `${this.state.sessions?.activeId ?? ""}:${this.state.activeViewId}:${this.state.presentation ?? "stack"}` : void 0;
8417
8468
  const currentView = `${state.sessions?.activeId ?? ""}:${state.activeViewId}:${state.presentation ?? "stack"}`;
8418
8469
  const viewChanged = previousView !== void 0 && previousView !== currentView;
8470
+ if (this.state?.sessions?.activeId !== state.sessions?.activeId) this.resetHistoryNavigation();
8419
8471
  if (viewChanged) {
8420
8472
  this.viewScroll.set(previousView, { top: this.scroll.scrollTop, live: this.offset === 0 });
8421
8473
  this.viewDisclosures.set(previousView, this.content.captureDisclosures(this.tasks.captureDisclosures()));
@@ -8446,12 +8498,14 @@ var NativeFrontend = class {
8446
8498
  this.tabs.visible = state.tabs.some((tab) => tab.id !== "main");
8447
8499
  this.viewTabsRow.visible = this.tabs.visible;
8448
8500
  this.sessionRow.visible = Boolean(state.sessions);
8449
- this.sessions.update(state.sessions?.items ?? [], state.sessions?.activeId ?? "", state.sessions?.busy);
8450
- this.newSession.focusable = !state.sessions?.busy;
8451
- this.sessionPicker.focusable = !state.sessions?.busy;
8452
- if (state.sessions?.busy && (this.newSession.focused || this.sessionPicker.focused)) this.getRenderable(`session:${state.sessions.activeId}`)?.focus();
8453
- this.newSession.attributes = state.sessions?.busy ? TextAttributes11.DIM : this.newSession.focused ? TextAttributes11.INVERSE : 0;
8454
- this.sessionPicker.attributes = state.sessions?.busy ? TextAttributes11.DIM : this.sessionPicker.focused ? TextAttributes11.INVERSE : 0;
8501
+ this.sessions.update((state.sessions?.items ?? []).map((item) => ({
8502
+ ...item,
8503
+ disabled: item.disabled ?? false,
8504
+ closeDisabled: item.closeDisabled ?? Boolean(state.sessions?.busy)
8505
+ })), state.sessions?.activeId ?? "");
8506
+ this.newSession.focusable = this.sessionPicker.focusable = true;
8507
+ this.newSession.attributes = this.newSession.focused ? TextAttributes11.INVERSE : 0;
8508
+ this.sessionPicker.attributes = this.sessionPicker.focused ? TextAttributes11.INVERSE : 0;
8455
8509
  this.tasks.replace(state.taskNotes ? [] : state.tasks);
8456
8510
  this.taskPane.visible = !state.taskNotes && state.tasks.length > 0;
8457
8511
  this.taskStrip.update(state.taskNotes);
@@ -8474,7 +8528,7 @@ var NativeFrontend = class {
8474
8528
  const index = state.suggestions.findIndex((item) => item.value === selected);
8475
8529
  if (index >= 0) this.suggestions.setSelectedIndex(index);
8476
8530
  }
8477
- this.suggestions.visible = state.suggestions.length > 0;
8531
+ this.suggestions.visible = this.historyIndex < 0 && state.suggestions.length > 0;
8478
8532
  this.suggestions.height = Math.min(4, state.suggestions.length || 1);
8479
8533
  this.prompt.content = styledText(state.prompt.trimEnd() || "❯");
8480
8534
  if (!this.editorInitialized) {
@@ -8797,6 +8851,7 @@ var NativeFrontend = class {
8797
8851
  const text = this.editor.plainText;
8798
8852
  const cursor = this.inputCursor();
8799
8853
  if (text === this.lastInput && cursor === this.lastCursor) return;
8854
+ if (this.historyIndex >= 0 && text !== this.history[this.historyIndex]) this.resetHistoryNavigation();
8800
8855
  this.lastInput = text;
8801
8856
  this.lastCursor = cursor;
8802
8857
  this.renderEnhance();
@@ -8813,19 +8868,31 @@ var NativeFrontend = class {
8813
8868
  this.history.unshift(text);
8814
8869
  this.history.length = Math.min(this.history.length, 1e3);
8815
8870
  }
8816
- this.historyIndex = -1;
8817
- this.savedInput = "";
8871
+ this.resetHistoryNavigation();
8818
8872
  this.editor.clear();
8819
8873
  this.emit({ type: "submit", text });
8820
8874
  this.editorChanged();
8821
8875
  }
8876
+ resetHistoryNavigation() {
8877
+ this.historyIndex = -1;
8878
+ this.savedInput = "";
8879
+ this.savedInputCursor = 0;
8880
+ }
8822
8881
  navigateHistory(direction) {
8823
8882
  if (this.history.length === 0) return;
8824
8883
  if (direction < 0) {
8825
- if (this.historyIndex < 0) this.savedInput = this.editor.plainText;
8884
+ if (this.historyIndex < 0) {
8885
+ this.savedInput = this.editor.plainText;
8886
+ this.savedInputCursor = this.inputCursor();
8887
+ }
8826
8888
  this.historyIndex = Math.min(this.history.length - 1, this.historyIndex + 1);
8827
- } else this.historyIndex = Math.max(-1, this.historyIndex - 1);
8828
- this.setInput(this.historyIndex < 0 ? this.savedInput : this.history[this.historyIndex]);
8889
+ } else {
8890
+ if (this.historyIndex < 0) return;
8891
+ this.historyIndex--;
8892
+ }
8893
+ this.suggestions.visible = false;
8894
+ if (this.historyIndex < 0) this.setInput(this.savedInput, this.savedInputCursor, true);
8895
+ else this.setInput(this.history[this.historyIndex], void 0, true);
8829
8896
  }
8830
8897
  acceptSuggestion() {
8831
8898
  const selected = this.suggestions.getSelectedOption();
@@ -8836,7 +8903,8 @@ var NativeFrontend = class {
8836
8903
  this.emitAction("completion", text);
8837
8904
  return true;
8838
8905
  }
8839
- setInput(text, cursor = text.length) {
8906
+ setInput(text, cursor = text.length, fromHistory = false) {
8907
+ if (!fromHistory) this.resetHistoryNavigation();
8840
8908
  this.editor.replaceText(text);
8841
8909
  this.placeInputCursor(text, cursor);
8842
8910
  this.editorInitialized = true;
@@ -8988,14 +9056,26 @@ var NativeFrontend = class {
8988
9056
  return;
8989
9057
  }
8990
9058
  if (key.name === "up" || key.name === "down") {
8991
- if (this.suggestions.visible) {
8992
- if (key.name === "up") this.suggestions.moveUp();
8993
- else this.suggestions.moveDown();
9059
+ if (this.renderer.currentFocusedRenderable === this.scroll) {
9060
+ this.scroll.scrollBy(key.name === "up" ? -1 : 1, "absolute");
8994
9061
  key.preventDefault();
8995
9062
  return;
8996
9063
  }
8997
- if (this.renderer.currentFocusedRenderable === this.scroll || this.offset > 0 || this.state?.activity?.processing && !this.editor.plainText) {
8998
- this.scroll.scrollBy(key.name === "up" ? -1 : 1, "absolute");
9064
+ if (this.paused || this.state?.input.enabled === false) {
9065
+ key.preventDefault();
9066
+ return;
9067
+ }
9068
+ if (this.suggestions.visible) {
9069
+ const index = this.suggestions.getSelectedIndex();
9070
+ const edge = key.name === "up" ? index <= 0 : index >= this.suggestions.options.length - 1;
9071
+ if (edge) {
9072
+ this.suggestions.visible = false;
9073
+ this.navigateHistory(key.name === "up" ? -1 : 1);
9074
+ key.preventDefault();
9075
+ return;
9076
+ }
9077
+ if (key.name === "up") this.suggestions.moveUp();
9078
+ else this.suggestions.moveDown();
8999
9079
  key.preventDefault();
9000
9080
  return;
9001
9081
  }
@@ -9006,6 +9086,7 @@ var NativeFrontend = class {
9006
9086
  key.preventDefault();
9007
9087
  return;
9008
9088
  }
9089
+ this.editorChanged();
9009
9090
  }
9010
9091
  if (this.paused || this.state?.input.enabled === false) {
9011
9092
  if (this.renderer.currentFocusedRenderable === this.editor) key.preventDefault();