omnius 1.0.884 → 1.0.887
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 +2 -2
- package/dist/library.js +125 -281
- package/dist/tui/native/worker.js +236 -71
- package/npm-shrinkwrap.json +801 -401
- package/package.json +5 -4
- package/vendor/moondream/LICENSE +21 -0
- package/vendor/moondream/README.md +11 -0
- package/vendor/moondream/index.cjs +292 -0
- package/vendor/moondream/index.d.ts +19 -0
- package/vendor/moondream/package.json +26 -0
- package/vendor/moondream/types.d.ts +208 -0
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createWriteStream } from "node:fs";
|
|
3
3
|
import { createInterface } from "node:readline";
|
|
4
4
|
import { PassThrough } from "node:stream";
|
|
5
|
-
import { CliRenderEvents as
|
|
5
|
+
import { CliRenderEvents as CliRenderEvents11, NativeSession, RGBA as RGBA4, createCliRenderer } from "@opentui/core";
|
|
6
6
|
|
|
7
7
|
// packages/cli/src/tui/native/components/frontend.ts
|
|
8
8
|
import {
|
|
@@ -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 =
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
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 ?? []
|
|
8450
|
-
|
|
8451
|
-
|
|
8452
|
-
|
|
8453
|
-
|
|
8454
|
-
this.
|
|
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) {
|
|
@@ -8724,6 +8778,28 @@ var NativeFrontend = class {
|
|
|
8724
8778
|
return visit(this.renderer.root);
|
|
8725
8779
|
}
|
|
8726
8780
|
onFrame = () => {
|
|
8781
|
+
if (this.destroyed) return;
|
|
8782
|
+
this.flushPendingInterfaceLayout();
|
|
8783
|
+
const height = Math.max(1, Math.min(8, this.editor.editorView.getTotalVirtualLineCount(), this.renderer.terminalHeight - 8));
|
|
8784
|
+
if (height !== this.editor.height) this.editor.height = height;
|
|
8785
|
+
this.layoutTabStrips();
|
|
8786
|
+
for (const media of this.context.mediaViews ?? []) media.reconcile({ x: this.scroll.viewport.x, y: this.scroll.viewport.y, width: this.scroll.viewport.width, height: this.scroll.viewport.height }, !this.paused && !this.modals.active);
|
|
8787
|
+
for (const model of this.context.modelViews ?? []) model.reconcile(this.scroll.viewport, !this.paused && !this.modals.active);
|
|
8788
|
+
this.modals.reconcileMedia();
|
|
8789
|
+
const offset2 = this.offset;
|
|
8790
|
+
if (offset2 === 0) this.newEntries = 0;
|
|
8791
|
+
this.liveButton.visible = offset2 > 0;
|
|
8792
|
+
const liveLabel = offset2 > 0 ? `↓ Live${this.newEntries ? ` · ${this.newEntries} new` : ""}` : "↓ Live";
|
|
8793
|
+
if (this.liveButton.plainText !== liveLabel) this.liveButton.content = liveLabel;
|
|
8794
|
+
const event = { type: "viewport", offset: this.scroll.scrollTop, height: this.scroll.viewport.height, width: this.scroll.viewport.width, total: this.scroll.scrollHeight };
|
|
8795
|
+
const signature = JSON.stringify(event);
|
|
8796
|
+
if (signature !== this.viewportSignature) {
|
|
8797
|
+
this.viewportSignature = signature;
|
|
8798
|
+
this.emit(event);
|
|
8799
|
+
}
|
|
8800
|
+
};
|
|
8801
|
+
/** Restore presentation after native layout, without requiring terminal drain. */
|
|
8802
|
+
flushPendingInterfaceLayout() {
|
|
8727
8803
|
if (this.destroyed) return;
|
|
8728
8804
|
if (this.pendingInterface) {
|
|
8729
8805
|
const state = this.pendingInterface;
|
|
@@ -8747,24 +8823,7 @@ var NativeFrontend = class {
|
|
|
8747
8823
|
this.scroll.scrollTo(restore.live ? this.scroll.scrollHeight : restore.top);
|
|
8748
8824
|
this.renderer.requestRender();
|
|
8749
8825
|
}
|
|
8750
|
-
|
|
8751
|
-
if (height !== this.editor.height) this.editor.height = height;
|
|
8752
|
-
this.layoutTabStrips();
|
|
8753
|
-
for (const media of this.context.mediaViews ?? []) media.reconcile({ x: this.scroll.viewport.x, y: this.scroll.viewport.y, width: this.scroll.viewport.width, height: this.scroll.viewport.height }, !this.paused && !this.modals.active);
|
|
8754
|
-
for (const model of this.context.modelViews ?? []) model.reconcile(this.scroll.viewport, !this.paused && !this.modals.active);
|
|
8755
|
-
this.modals.reconcileMedia();
|
|
8756
|
-
const offset2 = this.offset;
|
|
8757
|
-
if (offset2 === 0) this.newEntries = 0;
|
|
8758
|
-
this.liveButton.visible = offset2 > 0;
|
|
8759
|
-
const liveLabel = offset2 > 0 ? `↓ Live${this.newEntries ? ` · ${this.newEntries} new` : ""}` : "↓ Live";
|
|
8760
|
-
if (this.liveButton.plainText !== liveLabel) this.liveButton.content = liveLabel;
|
|
8761
|
-
const event = { type: "viewport", offset: this.scroll.scrollTop, height: this.scroll.viewport.height, width: this.scroll.viewport.width, total: this.scroll.scrollHeight };
|
|
8762
|
-
const signature = JSON.stringify(event);
|
|
8763
|
-
if (signature !== this.viewportSignature) {
|
|
8764
|
-
this.viewportSignature = signature;
|
|
8765
|
-
this.emit(event);
|
|
8766
|
-
}
|
|
8767
|
-
};
|
|
8826
|
+
}
|
|
8768
8827
|
onResize = () => {
|
|
8769
8828
|
this.layoutInstruments();
|
|
8770
8829
|
this.layoutTabStrips();
|
|
@@ -8792,6 +8851,7 @@ var NativeFrontend = class {
|
|
|
8792
8851
|
const text = this.editor.plainText;
|
|
8793
8852
|
const cursor = this.inputCursor();
|
|
8794
8853
|
if (text === this.lastInput && cursor === this.lastCursor) return;
|
|
8854
|
+
if (this.historyIndex >= 0 && text !== this.history[this.historyIndex]) this.resetHistoryNavigation();
|
|
8795
8855
|
this.lastInput = text;
|
|
8796
8856
|
this.lastCursor = cursor;
|
|
8797
8857
|
this.renderEnhance();
|
|
@@ -8808,19 +8868,31 @@ var NativeFrontend = class {
|
|
|
8808
8868
|
this.history.unshift(text);
|
|
8809
8869
|
this.history.length = Math.min(this.history.length, 1e3);
|
|
8810
8870
|
}
|
|
8811
|
-
this.
|
|
8812
|
-
this.savedInput = "";
|
|
8871
|
+
this.resetHistoryNavigation();
|
|
8813
8872
|
this.editor.clear();
|
|
8814
8873
|
this.emit({ type: "submit", text });
|
|
8815
8874
|
this.editorChanged();
|
|
8816
8875
|
}
|
|
8876
|
+
resetHistoryNavigation() {
|
|
8877
|
+
this.historyIndex = -1;
|
|
8878
|
+
this.savedInput = "";
|
|
8879
|
+
this.savedInputCursor = 0;
|
|
8880
|
+
}
|
|
8817
8881
|
navigateHistory(direction) {
|
|
8818
8882
|
if (this.history.length === 0) return;
|
|
8819
8883
|
if (direction < 0) {
|
|
8820
|
-
if (this.historyIndex < 0)
|
|
8884
|
+
if (this.historyIndex < 0) {
|
|
8885
|
+
this.savedInput = this.editor.plainText;
|
|
8886
|
+
this.savedInputCursor = this.inputCursor();
|
|
8887
|
+
}
|
|
8821
8888
|
this.historyIndex = Math.min(this.history.length - 1, this.historyIndex + 1);
|
|
8822
|
-
} else
|
|
8823
|
-
|
|
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);
|
|
8824
8896
|
}
|
|
8825
8897
|
acceptSuggestion() {
|
|
8826
8898
|
const selected = this.suggestions.getSelectedOption();
|
|
@@ -8831,7 +8903,8 @@ var NativeFrontend = class {
|
|
|
8831
8903
|
this.emitAction("completion", text);
|
|
8832
8904
|
return true;
|
|
8833
8905
|
}
|
|
8834
|
-
setInput(text, cursor = text.length) {
|
|
8906
|
+
setInput(text, cursor = text.length, fromHistory = false) {
|
|
8907
|
+
if (!fromHistory) this.resetHistoryNavigation();
|
|
8835
8908
|
this.editor.replaceText(text);
|
|
8836
8909
|
this.placeInputCursor(text, cursor);
|
|
8837
8910
|
this.editorInitialized = true;
|
|
@@ -8983,14 +9056,26 @@ var NativeFrontend = class {
|
|
|
8983
9056
|
return;
|
|
8984
9057
|
}
|
|
8985
9058
|
if (key.name === "up" || key.name === "down") {
|
|
8986
|
-
if (this.
|
|
8987
|
-
|
|
8988
|
-
else this.suggestions.moveDown();
|
|
9059
|
+
if (this.renderer.currentFocusedRenderable === this.scroll) {
|
|
9060
|
+
this.scroll.scrollBy(key.name === "up" ? -1 : 1, "absolute");
|
|
8989
9061
|
key.preventDefault();
|
|
8990
9062
|
return;
|
|
8991
9063
|
}
|
|
8992
|
-
if (this.
|
|
8993
|
-
|
|
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();
|
|
8994
9079
|
key.preventDefault();
|
|
8995
9080
|
return;
|
|
8996
9081
|
}
|
|
@@ -9001,6 +9086,7 @@ var NativeFrontend = class {
|
|
|
9001
9086
|
key.preventDefault();
|
|
9002
9087
|
return;
|
|
9003
9088
|
}
|
|
9089
|
+
this.editorChanged();
|
|
9004
9090
|
}
|
|
9005
9091
|
if (this.paused || this.state?.input.enabled === false) {
|
|
9006
9092
|
if (this.renderer.currentFocusedRenderable === this.editor) key.preventDefault();
|
|
@@ -9244,6 +9330,11 @@ var NativeFrontend = class {
|
|
|
9244
9330
|
if (this.state) this.update(this.state);
|
|
9245
9331
|
this.layoutInstruments();
|
|
9246
9332
|
this.renderer.requestRender();
|
|
9333
|
+
const pendingScroll = this.pendingScrollRestore;
|
|
9334
|
+
return () => {
|
|
9335
|
+
if (this.pendingInterface === state) this.pendingInterface = void 0;
|
|
9336
|
+
if (this.pendingScrollRestore === pendingScroll) this.pendingScrollRestore = void 0;
|
|
9337
|
+
};
|
|
9247
9338
|
}
|
|
9248
9339
|
async dispose() {
|
|
9249
9340
|
if (this.destroyed) return;
|
|
@@ -9338,6 +9429,70 @@ function installTerminalCursorDefaults(renderer2, session) {
|
|
|
9338
9429
|
return { restore, dispose };
|
|
9339
9430
|
}
|
|
9340
9431
|
|
|
9432
|
+
// packages/cli/src/tui/native/layout-barrier.ts
|
|
9433
|
+
import { CliRenderEvents as CliRenderEvents10 } from "@opentui/core";
|
|
9434
|
+
var NATIVE_INTERFACE_LAYOUT_TIMEOUT_MS = 1e3;
|
|
9435
|
+
function waitForNativeLayout(renderer2, applyPendingLayout, options = {}) {
|
|
9436
|
+
const deadline = options.deadline ?? performance.now() + (options.timeoutMs ?? NATIVE_INTERFACE_LAYOUT_TIMEOUT_MS);
|
|
9437
|
+
return new Promise((resolve2, reject) => {
|
|
9438
|
+
let settled = false;
|
|
9439
|
+
let queued = false;
|
|
9440
|
+
let timer;
|
|
9441
|
+
const finish = (error) => {
|
|
9442
|
+
if (settled) return;
|
|
9443
|
+
settled = true;
|
|
9444
|
+
clearTimeout(timer);
|
|
9445
|
+
renderer2.removePostProcessFn(afterLayout);
|
|
9446
|
+
renderer2.off(CliRenderEvents10.DESTROY, destroyed);
|
|
9447
|
+
options.signal?.removeEventListener("abort", aborted);
|
|
9448
|
+
if (error) reject(error);
|
|
9449
|
+
else resolve2();
|
|
9450
|
+
};
|
|
9451
|
+
const destroyed = () => finish(new Error("OpenTUI closed before interface layout completed"));
|
|
9452
|
+
const aborted = () => finish(new Error("OpenTUI interface layout was cancelled"));
|
|
9453
|
+
const afterLayout = (_buffer) => {
|
|
9454
|
+
if (queued || settled) return;
|
|
9455
|
+
queued = true;
|
|
9456
|
+
queueMicrotask(() => {
|
|
9457
|
+
if (settled) return;
|
|
9458
|
+
if (performance.now() >= deadline) {
|
|
9459
|
+
timedOut();
|
|
9460
|
+
return;
|
|
9461
|
+
}
|
|
9462
|
+
try {
|
|
9463
|
+
applyPendingLayout();
|
|
9464
|
+
finish();
|
|
9465
|
+
} catch (error) {
|
|
9466
|
+
finish(error instanceof Error ? error : new Error("OpenTUI interface layout failed"));
|
|
9467
|
+
}
|
|
9468
|
+
});
|
|
9469
|
+
};
|
|
9470
|
+
renderer2.addPostProcessFn(afterLayout);
|
|
9471
|
+
renderer2.once(CliRenderEvents10.DESTROY, destroyed);
|
|
9472
|
+
options.signal?.addEventListener("abort", aborted, { once: true });
|
|
9473
|
+
if (options.signal?.aborted) {
|
|
9474
|
+
aborted();
|
|
9475
|
+
return;
|
|
9476
|
+
}
|
|
9477
|
+
if (renderer2.isDestroyed) {
|
|
9478
|
+
destroyed();
|
|
9479
|
+
return;
|
|
9480
|
+
}
|
|
9481
|
+
const timeoutMs = deadline - performance.now();
|
|
9482
|
+
const timedOut = () => finish(new Error("OpenTUI interface layout did not complete; terminal output may be paused"));
|
|
9483
|
+
if (timeoutMs <= 0) {
|
|
9484
|
+
timedOut();
|
|
9485
|
+
return;
|
|
9486
|
+
}
|
|
9487
|
+
timer = setTimeout(timedOut, timeoutMs);
|
|
9488
|
+
try {
|
|
9489
|
+
renderer2.requestRender();
|
|
9490
|
+
} catch (error) {
|
|
9491
|
+
finish(error instanceof Error ? error : new Error("OpenTUI interface layout failed"));
|
|
9492
|
+
}
|
|
9493
|
+
});
|
|
9494
|
+
}
|
|
9495
|
+
|
|
9341
9496
|
// packages/cli/src/tui/native/worker.ts
|
|
9342
9497
|
var replies = createWriteStream("", { fd: 3, autoClose: false });
|
|
9343
9498
|
var reply = (message) => replies.write(JSON.stringify(message) + "\n");
|
|
@@ -9347,9 +9502,11 @@ var frontend;
|
|
|
9347
9502
|
var cursorDefaults;
|
|
9348
9503
|
var stopping = false;
|
|
9349
9504
|
var failed = false;
|
|
9505
|
+
var layoutController = new AbortController();
|
|
9350
9506
|
async function close() {
|
|
9351
9507
|
if (stopping) return;
|
|
9352
9508
|
stopping = true;
|
|
9509
|
+
layoutController.abort();
|
|
9353
9510
|
try {
|
|
9354
9511
|
await frontend?.dispose();
|
|
9355
9512
|
await cursorDefaults?.restore();
|
|
@@ -9369,27 +9526,35 @@ async function fail(error) {
|
|
|
9369
9526
|
});
|
|
9370
9527
|
replies.end(() => process.exit(1));
|
|
9371
9528
|
}
|
|
9372
|
-
async function command(message) {
|
|
9529
|
+
async function command(message, layoutDeadline) {
|
|
9373
9530
|
if (message.type === "command") {
|
|
9374
9531
|
frontend.command(message.command);
|
|
9375
9532
|
return;
|
|
9376
9533
|
}
|
|
9377
|
-
if (message.type === "interface-capture") {
|
|
9378
|
-
|
|
9379
|
-
|
|
9380
|
-
|
|
9381
|
-
|
|
9382
|
-
|
|
9383
|
-
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9534
|
+
if (message.type === "interface-capture" || message.type === "interface-restore") {
|
|
9535
|
+
if (performance.now() >= layoutDeadline) {
|
|
9536
|
+
reply({ type: "request-error", id: message.id, message: "OpenTUI interface request expired before layout could begin" });
|
|
9537
|
+
return;
|
|
9538
|
+
}
|
|
9539
|
+
let cancelRestore;
|
|
9540
|
+
try {
|
|
9541
|
+
await waitForNativeLayout(renderer, () => {
|
|
9542
|
+
if (message.type === "interface-restore") cancelRestore = frontend.restoreInterfaceState(message.state);
|
|
9543
|
+
frontend.flushPendingInterfaceLayout();
|
|
9544
|
+
}, { signal: layoutController.signal, deadline: layoutDeadline });
|
|
9545
|
+
} catch (error) {
|
|
9546
|
+
cancelRestore?.();
|
|
9547
|
+
if (!stopping) reply({ type: "request-error", id: message.id, message: error instanceof Error ? error.message : "OpenTUI interface layout failed" });
|
|
9548
|
+
return;
|
|
9549
|
+
}
|
|
9550
|
+
if (stopping) return;
|
|
9551
|
+
if (message.type === "interface-capture") reply({ type: "interface-state", id: message.id, state: frontend.captureInterfaceState() });
|
|
9552
|
+
else reply({ type: "ack", id: message.id });
|
|
9387
9553
|
return;
|
|
9388
9554
|
}
|
|
9389
9555
|
if (message.type === "state") {
|
|
9390
9556
|
frontend.update(message.snapshot, message.content);
|
|
9391
9557
|
renderer.requestRender();
|
|
9392
|
-
await renderer.idle();
|
|
9393
9558
|
} else if (message.type === "suspend") {
|
|
9394
9559
|
frontend.pauseMedia();
|
|
9395
9560
|
await cursorDefaults.restore();
|
|
@@ -9397,7 +9562,6 @@ async function command(message) {
|
|
|
9397
9562
|
} else if (message.type === "resume") {
|
|
9398
9563
|
await renderer.resume();
|
|
9399
9564
|
renderer.requestRender();
|
|
9400
|
-
await renderer.idle();
|
|
9401
9565
|
await cursorDefaults.restore();
|
|
9402
9566
|
} else if (message.type === "stop") await close();
|
|
9403
9567
|
reply({ type: "ack", id: message.id });
|
|
@@ -9423,10 +9587,10 @@ try {
|
|
|
9423
9587
|
maxFps: 60,
|
|
9424
9588
|
clearOnShutdown: false
|
|
9425
9589
|
});
|
|
9426
|
-
renderer.on(
|
|
9590
|
+
renderer.on(CliRenderEvents11.RENDER_ERROR, (event) => {
|
|
9427
9591
|
void fail(event.error);
|
|
9428
9592
|
});
|
|
9429
|
-
renderer.on(
|
|
9593
|
+
renderer.on(CliRenderEvents11.HANDLER_ERROR, (event) => {
|
|
9430
9594
|
void fail(event.error);
|
|
9431
9595
|
});
|
|
9432
9596
|
renderer.on("error", (event) => {
|
|
@@ -9437,6 +9601,7 @@ try {
|
|
|
9437
9601
|
const controls = createInterface({ input: process.stdin, crlfDelay: Infinity });
|
|
9438
9602
|
let pending = Promise.resolve();
|
|
9439
9603
|
controls.on("line", (line) => {
|
|
9604
|
+
const layoutDeadline = performance.now() + NATIVE_INTERFACE_LAYOUT_TIMEOUT_MS;
|
|
9440
9605
|
let message;
|
|
9441
9606
|
try {
|
|
9442
9607
|
message = JSON.parse(line);
|
|
@@ -9452,7 +9617,7 @@ try {
|
|
|
9452
9617
|
} catch (error) {
|
|
9453
9618
|
void fail(error);
|
|
9454
9619
|
}
|
|
9455
|
-
} else pending = pending.then(() => command(message)).catch(fail);
|
|
9620
|
+
} else pending = pending.then(() => command(message, layoutDeadline)).catch(fail);
|
|
9456
9621
|
});
|
|
9457
9622
|
controls.on("close", () => {
|
|
9458
9623
|
void pending.then(close).finally(() => process.exit(0));
|