omnius 1.0.323 → 1.0.325
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 +977 -123
- package/npm-shrinkwrap.json +8 -8
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -160050,7 +160050,7 @@ var require_constants5 = __commonJS({
|
|
|
160050
160050
|
writable: false,
|
|
160051
160051
|
configurable: false
|
|
160052
160052
|
};
|
|
160053
|
-
var
|
|
160053
|
+
var states2 = {
|
|
160054
160054
|
CONNECTING: 0,
|
|
160055
160055
|
OPEN: 1,
|
|
160056
160056
|
CLOSING: 2,
|
|
@@ -160086,7 +160086,7 @@ var require_constants5 = __commonJS({
|
|
|
160086
160086
|
uid,
|
|
160087
160087
|
sentCloseFrameState,
|
|
160088
160088
|
staticPropertyDescriptors,
|
|
160089
|
-
states,
|
|
160089
|
+
states: states2,
|
|
160090
160090
|
opcodes,
|
|
160091
160091
|
maxUnsigned16Bit,
|
|
160092
160092
|
parserStates,
|
|
@@ -160100,21 +160100,21 @@ var require_constants5 = __commonJS({
|
|
|
160100
160100
|
var require_util7 = __commonJS({
|
|
160101
160101
|
"../node_modules/undici/lib/web/websocket/util.js"(exports, module) {
|
|
160102
160102
|
"use strict";
|
|
160103
|
-
var { states, opcodes } = require_constants5();
|
|
160103
|
+
var { states: states2, opcodes } = require_constants5();
|
|
160104
160104
|
var { isUtf8 } = __require("node:buffer");
|
|
160105
160105
|
var { removeHTTPWhitespace } = require_data_url();
|
|
160106
160106
|
var { collectASequenceOfCodePointsFast } = require_infra();
|
|
160107
160107
|
function isConnecting(readyState) {
|
|
160108
|
-
return readyState ===
|
|
160108
|
+
return readyState === states2.CONNECTING;
|
|
160109
160109
|
}
|
|
160110
160110
|
function isEstablished(readyState) {
|
|
160111
|
-
return readyState ===
|
|
160111
|
+
return readyState === states2.OPEN;
|
|
160112
160112
|
}
|
|
160113
160113
|
function isClosing(readyState) {
|
|
160114
|
-
return readyState ===
|
|
160114
|
+
return readyState === states2.CLOSING;
|
|
160115
160115
|
}
|
|
160116
160116
|
function isClosed(readyState) {
|
|
160117
|
-
return readyState ===
|
|
160117
|
+
return readyState === states2.CLOSED;
|
|
160118
160118
|
}
|
|
160119
160119
|
function fireEvent(e2, target, eventFactory = (type, init2) => new Event(type, init2), eventInitDict = {}) {
|
|
160120
160120
|
const event = eventFactory(e2, eventInitDict);
|
|
@@ -160382,7 +160382,7 @@ var require_frame = __commonJS({
|
|
|
160382
160382
|
var require_connection = __commonJS({
|
|
160383
160383
|
"../node_modules/undici/lib/web/websocket/connection.js"(exports, module) {
|
|
160384
160384
|
"use strict";
|
|
160385
|
-
var { uid, states, sentCloseFrameState, emptyBuffer, opcodes } = require_constants5();
|
|
160385
|
+
var { uid, states: states2, sentCloseFrameState, emptyBuffer, opcodes } = require_constants5();
|
|
160386
160386
|
var { parseExtensions, isClosed, isClosing, isEstablished, isConnecting, validateCloseCodeAndReason } = require_util7();
|
|
160387
160387
|
var { makeRequest } = require_request2();
|
|
160388
160388
|
var { fetching } = require_fetch();
|
|
@@ -160489,7 +160489,7 @@ var require_connection = __commonJS({
|
|
|
160489
160489
|
if (isClosed(object.readyState) || isClosing(object.readyState)) {
|
|
160490
160490
|
} else if (!isEstablished(object.readyState)) {
|
|
160491
160491
|
failWebsocketConnection(object);
|
|
160492
|
-
object.readyState =
|
|
160492
|
+
object.readyState = states2.CLOSING;
|
|
160493
160493
|
} else if (!object.closeState.has(sentCloseFrameState.SENT) && !object.closeState.has(sentCloseFrameState.RECEIVED)) {
|
|
160494
160494
|
const frame = new WebsocketFrameSend();
|
|
160495
160495
|
if (reason.length !== 0 && code8 === null) {
|
|
@@ -160510,9 +160510,9 @@ var require_connection = __commonJS({
|
|
|
160510
160510
|
}
|
|
160511
160511
|
object.socket.write(frame.createFrame(opcodes.CLOSE));
|
|
160512
160512
|
object.closeState.add(sentCloseFrameState.SENT);
|
|
160513
|
-
object.readyState =
|
|
160513
|
+
object.readyState = states2.CLOSING;
|
|
160514
160514
|
} else {
|
|
160515
|
-
object.readyState =
|
|
160515
|
+
object.readyState = states2.CLOSING;
|
|
160516
160516
|
}
|
|
160517
160517
|
}
|
|
160518
160518
|
function failWebsocketConnection(handler, code8, reason, cause) {
|
|
@@ -160633,7 +160633,7 @@ var require_receiver = __commonJS({
|
|
|
160633
160633
|
"use strict";
|
|
160634
160634
|
var { Writable } = __require("node:stream");
|
|
160635
160635
|
var assert = __require("node:assert");
|
|
160636
|
-
var { parserStates, opcodes, states, emptyBuffer, sentCloseFrameState } = require_constants5();
|
|
160636
|
+
var { parserStates, opcodes, states: states2, emptyBuffer, sentCloseFrameState } = require_constants5();
|
|
160637
160637
|
var {
|
|
160638
160638
|
isValidStatusCode,
|
|
160639
160639
|
isValidOpcode,
|
|
@@ -160921,7 +160921,7 @@ var require_receiver = __commonJS({
|
|
|
160921
160921
|
this.#handler.socket.write(closeFrame.createFrame(opcodes.CLOSE));
|
|
160922
160922
|
this.#handler.closeState.add(sentCloseFrameState.SENT);
|
|
160923
160923
|
}
|
|
160924
|
-
this.#handler.readyState =
|
|
160924
|
+
this.#handler.readyState = states2.CLOSING;
|
|
160925
160925
|
this.#handler.closeState.add(sentCloseFrameState.RECEIVED);
|
|
160926
160926
|
return false;
|
|
160927
160927
|
} else if (opcode === opcodes.PING) {
|
|
@@ -161040,7 +161040,7 @@ var require_websocket = __commonJS({
|
|
|
161040
161040
|
var { webidl } = require_webidl();
|
|
161041
161041
|
var { URLSerializer } = require_data_url();
|
|
161042
161042
|
var { environmentSettingsObject } = require_util4();
|
|
161043
|
-
var { staticPropertyDescriptors, states, sentCloseFrameState, sendHints, opcodes } = require_constants5();
|
|
161043
|
+
var { staticPropertyDescriptors, states: states2, sentCloseFrameState, sendHints, opcodes } = require_constants5();
|
|
161044
161044
|
var {
|
|
161045
161045
|
isConnecting,
|
|
161046
161046
|
isEstablished,
|
|
@@ -161093,7 +161093,7 @@ var require_websocket = __commonJS({
|
|
|
161093
161093
|
}
|
|
161094
161094
|
},
|
|
161095
161095
|
onSocketError: (err) => {
|
|
161096
|
-
this.#handler.readyState =
|
|
161096
|
+
this.#handler.readyState = states2.CLOSING;
|
|
161097
161097
|
if (channels.socketError.hasSubscribers) {
|
|
161098
161098
|
channels.socketError.publish(err);
|
|
161099
161099
|
}
|
|
@@ -161116,7 +161116,7 @@ var require_websocket = __commonJS({
|
|
|
161116
161116
|
});
|
|
161117
161117
|
}
|
|
161118
161118
|
},
|
|
161119
|
-
readyState:
|
|
161119
|
+
readyState: states2.CONNECTING,
|
|
161120
161120
|
socket: null,
|
|
161121
161121
|
closeState: /* @__PURE__ */ new Set(),
|
|
161122
161122
|
controller: null,
|
|
@@ -161327,7 +161327,7 @@ var require_websocket = __commonJS({
|
|
|
161327
161327
|
parser2.on("error", (err) => this.#handler.onParserError(err));
|
|
161328
161328
|
this.#parser = parser2;
|
|
161329
161329
|
this.#sendQueue = new SendQueue(response.socket);
|
|
161330
|
-
this.#handler.readyState =
|
|
161330
|
+
this.#handler.readyState = states2.OPEN;
|
|
161331
161331
|
const extensions = response.headersList.get("sec-websocket-extensions");
|
|
161332
161332
|
if (extensions !== null) {
|
|
161333
161333
|
this.#extensions = extensions;
|
|
@@ -161353,7 +161353,7 @@ var require_websocket = __commonJS({
|
|
|
161353
161353
|
}
|
|
161354
161354
|
}
|
|
161355
161355
|
#onMessage(type, data) {
|
|
161356
|
-
if (this.#handler.readyState !==
|
|
161356
|
+
if (this.#handler.readyState !== states2.OPEN) {
|
|
161357
161357
|
return;
|
|
161358
161358
|
}
|
|
161359
161359
|
let dataForEvent;
|
|
@@ -161392,7 +161392,7 @@ var require_websocket = __commonJS({
|
|
|
161392
161392
|
code8 = result.code ?? 1005;
|
|
161393
161393
|
reason = result.reason;
|
|
161394
161394
|
}
|
|
161395
|
-
this.#handler.readyState =
|
|
161395
|
+
this.#handler.readyState = states2.CLOSED;
|
|
161396
161396
|
if (!this.#handler.closeState.has(sentCloseFrameState.RECEIVED)) {
|
|
161397
161397
|
code8 = 1006;
|
|
161398
161398
|
fireEvent("error", this, (type, init2) => new ErrorEvent2(type, init2), {
|
|
@@ -161433,10 +161433,10 @@ var require_websocket = __commonJS({
|
|
|
161433
161433
|
};
|
|
161434
161434
|
var { ping: ping2 } = WebSocket6;
|
|
161435
161435
|
Reflect.deleteProperty(WebSocket6, "ping");
|
|
161436
|
-
WebSocket6.CONNECTING = WebSocket6.prototype.CONNECTING =
|
|
161437
|
-
WebSocket6.OPEN = WebSocket6.prototype.OPEN =
|
|
161438
|
-
WebSocket6.CLOSING = WebSocket6.prototype.CLOSING =
|
|
161439
|
-
WebSocket6.CLOSED = WebSocket6.prototype.CLOSED =
|
|
161436
|
+
WebSocket6.CONNECTING = WebSocket6.prototype.CONNECTING = states2.CONNECTING;
|
|
161437
|
+
WebSocket6.OPEN = WebSocket6.prototype.OPEN = states2.OPEN;
|
|
161438
|
+
WebSocket6.CLOSING = WebSocket6.prototype.CLOSING = states2.CLOSING;
|
|
161439
|
+
WebSocket6.CLOSED = WebSocket6.prototype.CLOSED = states2.CLOSED;
|
|
161440
161440
|
Object.defineProperties(WebSocket6.prototype, {
|
|
161441
161441
|
CONNECTING: staticPropertyDescriptors,
|
|
161442
161442
|
OPEN: staticPropertyDescriptors,
|
|
@@ -161602,7 +161602,7 @@ var require_websocketstream = __commonJS({
|
|
|
161602
161602
|
"use strict";
|
|
161603
161603
|
var { createDeferredPromise: createDeferredPromise2 } = require_promise();
|
|
161604
161604
|
var { environmentSettingsObject } = require_util4();
|
|
161605
|
-
var { states, opcodes, sentCloseFrameState } = require_constants5();
|
|
161605
|
+
var { states: states2, opcodes, sentCloseFrameState } = require_constants5();
|
|
161606
161606
|
var { webidl } = require_webidl();
|
|
161607
161607
|
var { getURLRecord, isValidSubprotocol, isEstablished, utf8Decode } = require_util7();
|
|
161608
161608
|
var { establishWebSocketConnection, failWebsocketConnection, closeWebSocketConnection } = require_connection();
|
|
@@ -161646,7 +161646,7 @@ var require_websocketstream = __commonJS({
|
|
|
161646
161646
|
}
|
|
161647
161647
|
},
|
|
161648
161648
|
onSocketError: (err) => {
|
|
161649
|
-
this.#handler.readyState =
|
|
161649
|
+
this.#handler.readyState = states2.CLOSING;
|
|
161650
161650
|
if (channels.socketError.hasSubscribers) {
|
|
161651
161651
|
channels.socketError.publish(err);
|
|
161652
161652
|
}
|
|
@@ -161657,7 +161657,7 @@ var require_websocketstream = __commonJS({
|
|
|
161657
161657
|
},
|
|
161658
161658
|
onPong: () => {
|
|
161659
161659
|
},
|
|
161660
|
-
readyState:
|
|
161660
|
+
readyState: states2.CONNECTING,
|
|
161661
161661
|
socket: null,
|
|
161662
161662
|
closeState: /* @__PURE__ */ new Set(),
|
|
161663
161663
|
controller: null,
|
|
@@ -161699,7 +161699,7 @@ var require_websocketstream = __commonJS({
|
|
|
161699
161699
|
signal.addEventListener("abort", () => {
|
|
161700
161700
|
if (!isEstablished(this.#handler.readyState)) {
|
|
161701
161701
|
failWebsocketConnection(this.#handler);
|
|
161702
|
-
this.#handler.readyState =
|
|
161702
|
+
this.#handler.readyState = states2.CLOSING;
|
|
161703
161703
|
this.#openedPromise.reject(signal.reason);
|
|
161704
161704
|
this.#closedPromise.reject(signal.reason);
|
|
161705
161705
|
this.#handshakeAborted = true;
|
|
@@ -161770,7 +161770,7 @@ var require_websocketstream = __commonJS({
|
|
|
161770
161770
|
parser2.on("drain", () => this.#handler.onParserDrain());
|
|
161771
161771
|
parser2.on("error", (err) => this.#handler.onParserError(err));
|
|
161772
161772
|
this.#parser = parser2;
|
|
161773
|
-
this.#handler.readyState =
|
|
161773
|
+
this.#handler.readyState = states2.OPEN;
|
|
161774
161774
|
const extensions = parsedExtensions ?? "";
|
|
161775
161775
|
const protocol = response.headersList.get("sec-websocket-protocol") ?? "";
|
|
161776
161776
|
const readable = new ReadableStream({
|
|
@@ -161801,7 +161801,7 @@ var require_websocketstream = __commonJS({
|
|
|
161801
161801
|
}
|
|
161802
161802
|
/** @type {import('../websocket').Handler['onMessage']} */
|
|
161803
161803
|
#onMessage(type, data) {
|
|
161804
|
-
if (this.#handler.readyState !==
|
|
161804
|
+
if (this.#handler.readyState !== states2.OPEN) {
|
|
161805
161805
|
return;
|
|
161806
161806
|
}
|
|
161807
161807
|
let chunk;
|
|
@@ -161820,7 +161820,7 @@ var require_websocketstream = __commonJS({
|
|
|
161820
161820
|
/** @type {import('../websocket').Handler['onSocketClose']} */
|
|
161821
161821
|
#onSocketClose() {
|
|
161822
161822
|
const wasClean = this.#handler.closeState.has(sentCloseFrameState.SENT) && this.#handler.closeState.has(sentCloseFrameState.RECEIVED);
|
|
161823
|
-
this.#handler.readyState =
|
|
161823
|
+
this.#handler.readyState = states2.CLOSED;
|
|
161824
161824
|
if (this.#handshakeAborted) {
|
|
161825
161825
|
return;
|
|
161826
161826
|
}
|
|
@@ -563637,11 +563637,11 @@ var init_streaming_executor = __esm({
|
|
|
563637
563637
|
}
|
|
563638
563638
|
/** Get the current state of all tool calls */
|
|
563639
563639
|
getStates() {
|
|
563640
|
-
const
|
|
563640
|
+
const states2 = /* @__PURE__ */ new Map();
|
|
563641
563641
|
for (const [id, entry] of this.tools) {
|
|
563642
|
-
|
|
563642
|
+
states2.set(id, entry.state);
|
|
563643
563643
|
}
|
|
563644
|
-
return
|
|
563644
|
+
return states2;
|
|
563645
563645
|
}
|
|
563646
563646
|
/** Get count of tools in each state */
|
|
563647
563647
|
getCounts() {
|
|
@@ -595348,6 +595348,23 @@ __export(task_complete_box_exports, {
|
|
|
595348
595348
|
renderSessionHistoryBox: () => renderSessionHistoryBox,
|
|
595349
595349
|
renderTaskCompleteBox: () => renderTaskCompleteBox
|
|
595350
595350
|
});
|
|
595351
|
+
function refreshBoxPalette() {
|
|
595352
|
+
if (themeMode() === "system") {
|
|
595353
|
+
GREEN = DEFAULT_FG;
|
|
595354
|
+
FG_BORDER = DEFAULT_FG;
|
|
595355
|
+
FG_TITLE = DEFAULT_BOLD_FG;
|
|
595356
|
+
FG_METRIC = DEFAULT_FG;
|
|
595357
|
+
FG_LABEL = DEFAULT_FG;
|
|
595358
|
+
return;
|
|
595359
|
+
}
|
|
595360
|
+
const accent = tuiAccent();
|
|
595361
|
+
const borderColor = accent >= 0 ? accent : TASK_COMPLETE_GREEN_256;
|
|
595362
|
+
GREEN = `\x1B[38;5;${borderColor}m`;
|
|
595363
|
+
FG_BORDER = `\x1B[38;5;${borderColor}m`;
|
|
595364
|
+
FG_TITLE = `\x1B[1;38;5;${borderColor}m`;
|
|
595365
|
+
FG_METRIC = "\x1B[38;5;222m";
|
|
595366
|
+
FG_LABEL = "\x1B[38;5;147m";
|
|
595367
|
+
}
|
|
595351
595368
|
function deriveTitle(task) {
|
|
595352
595369
|
if (!task || !task.trim()) return "Task Complete";
|
|
595353
595370
|
const source = task.replace(/^[\s\S]*?\n---\s*\n\s*NEW TASK:\s*/i, "").replace(/^NEW TASK:\s*/i, "").replace(/<task-handoff>[\s\S]*?<\/task-handoff>/gi, " ").replace(/<session-recap>[\s\S]*?<\/session-recap>/gi, " ").replace(/^\[task_(?:boundary|summary)\][\s\S]*?(?=\n\n|$)/gim, " ");
|
|
@@ -595540,6 +595557,7 @@ function buildLabeledFooterLines(label, items, width) {
|
|
|
595540
595557
|
return lines;
|
|
595541
595558
|
}
|
|
595542
595559
|
function buildBoxLines(data, width) {
|
|
595560
|
+
refreshBoxPalette();
|
|
595543
595561
|
const w = Math.max(40, width);
|
|
595544
595562
|
const title = deriveTitle(data.task);
|
|
595545
595563
|
const metrics2 = buildMetricsChip(data);
|
|
@@ -595579,6 +595597,7 @@ function buildBoxLines(data, width) {
|
|
|
595579
595597
|
return lines;
|
|
595580
595598
|
}
|
|
595581
595599
|
function buildSessionHistoryBoxLines(data, width) {
|
|
595600
|
+
refreshBoxPalette();
|
|
595582
595601
|
const w = Math.max(40, width);
|
|
595583
595602
|
const title = deriveTitle(data.title || "Session History");
|
|
595584
595603
|
const metrics2 = buildSessionHistoryMetricsChip(data);
|
|
@@ -595710,11 +595729,12 @@ function detectProvenanceAnchors(toolOutputs) {
|
|
|
595710
595729
|
}
|
|
595711
595730
|
return [...out].slice(0, 16);
|
|
595712
595731
|
}
|
|
595713
|
-
var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, TASK_COMPLETE_GREEN_256, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
|
|
595732
|
+
var BOX_TL, BOX_TR, BOX_BL, BOX_BR, BOX_H, BOX_V, BOX_TJ_L, BOX_TJ_R, RESET, TASK_COMPLETE_GREEN_256, DEFAULT_FG, DEFAULT_BOLD_FG, GREEN, FG_BORDER, FG_TITLE, FG_METRIC, FG_LABEL;
|
|
595714
595733
|
var init_task_complete_box = __esm({
|
|
595715
595734
|
"packages/cli/src/tui/task-complete-box.ts"() {
|
|
595716
595735
|
"use strict";
|
|
595717
595736
|
init_text_selection();
|
|
595737
|
+
init_theme();
|
|
595718
595738
|
BOX_TL = "╭";
|
|
595719
595739
|
BOX_TR = "╮";
|
|
595720
595740
|
BOX_BL = "╰";
|
|
@@ -595725,6 +595745,8 @@ var init_task_complete_box = __esm({
|
|
|
595725
595745
|
BOX_TJ_R = "┤";
|
|
595726
595746
|
RESET = "\x1B[0m";
|
|
595727
595747
|
TASK_COMPLETE_GREEN_256 = 154;
|
|
595748
|
+
DEFAULT_FG = "\x1B[39m";
|
|
595749
|
+
DEFAULT_BOLD_FG = "\x1B[1;39m";
|
|
595728
595750
|
GREEN = `\x1B[38;5;${TASK_COMPLETE_GREEN_256}m`;
|
|
595729
595751
|
FG_BORDER = `\x1B[38;5;${TASK_COMPLETE_GREEN_256}m`;
|
|
595730
595752
|
FG_TITLE = `\x1B[1;38;5;${TASK_COMPLETE_GREEN_256}m`;
|
|
@@ -596638,10 +596660,61 @@ var init_secret_redactor = __esm({
|
|
|
596638
596660
|
}
|
|
596639
596661
|
});
|
|
596640
596662
|
|
|
596663
|
+
// packages/cli/src/tui/tool-collapse-store.ts
|
|
596664
|
+
function isCollapsibleBlock(id) {
|
|
596665
|
+
return states.has(id);
|
|
596666
|
+
}
|
|
596667
|
+
function ensureCollapsible(id) {
|
|
596668
|
+
let s2 = states.get(id);
|
|
596669
|
+
if (s2 === void 0) {
|
|
596670
|
+
s2 = globalDefault;
|
|
596671
|
+
states.set(id, s2);
|
|
596672
|
+
}
|
|
596673
|
+
return s2;
|
|
596674
|
+
}
|
|
596675
|
+
function getCollapseState(id) {
|
|
596676
|
+
return states.get(id) ?? globalDefault;
|
|
596677
|
+
}
|
|
596678
|
+
function setCollapseState(id, state) {
|
|
596679
|
+
states.set(id, state);
|
|
596680
|
+
}
|
|
596681
|
+
function toggleTitle(id) {
|
|
596682
|
+
const cur = getCollapseState(id);
|
|
596683
|
+
setCollapseState(id, cur === "collapsed" ? "preview" : "collapsed");
|
|
596684
|
+
}
|
|
596685
|
+
function toggleMore(id) {
|
|
596686
|
+
const cur = getCollapseState(id);
|
|
596687
|
+
setCollapseState(id, cur === "expanded" ? "preview" : "expanded");
|
|
596688
|
+
}
|
|
596689
|
+
function toggleAll() {
|
|
596690
|
+
let anyOpen = false;
|
|
596691
|
+
for (const s2 of states.values()) {
|
|
596692
|
+
if (s2 !== "collapsed") {
|
|
596693
|
+
anyOpen = true;
|
|
596694
|
+
break;
|
|
596695
|
+
}
|
|
596696
|
+
}
|
|
596697
|
+
const next = anyOpen ? "collapsed" : "preview";
|
|
596698
|
+
for (const id of states.keys()) states.set(id, next);
|
|
596699
|
+
globalDefault = next;
|
|
596700
|
+
}
|
|
596701
|
+
var PREVIEW_ROWS, READ_MORE_LABEL, READ_LESS_LABEL, globalDefault, states;
|
|
596702
|
+
var init_tool_collapse_store = __esm({
|
|
596703
|
+
"packages/cli/src/tui/tool-collapse-store.ts"() {
|
|
596704
|
+
"use strict";
|
|
596705
|
+
PREVIEW_ROWS = 8;
|
|
596706
|
+
READ_MORE_LABEL = "read more…";
|
|
596707
|
+
READ_LESS_LABEL = "read less";
|
|
596708
|
+
globalDefault = "preview";
|
|
596709
|
+
states = /* @__PURE__ */ new Map();
|
|
596710
|
+
}
|
|
596711
|
+
});
|
|
596712
|
+
|
|
596641
596713
|
// packages/cli/src/tui/render.ts
|
|
596642
596714
|
var render_exports = {};
|
|
596643
596715
|
__export(render_exports, {
|
|
596644
596716
|
SLASH_COMMANDS: () => SLASH_COMMANDS2,
|
|
596717
|
+
applyCollapseToBox: () => applyCollapseToBox,
|
|
596645
596718
|
breakTelegramCoalesce: () => breakTelegramCoalesce,
|
|
596646
596719
|
c: () => c3,
|
|
596647
596720
|
charWidth: () => charWidth2,
|
|
@@ -597066,6 +597139,52 @@ function buildToolBottom(width, colorCode) {
|
|
|
597066
597139
|
const border = toolColorSeq(colorCode);
|
|
597067
597140
|
return `${border}${BOX_BL2}${BOX_H2.repeat(Math.max(0, width - 2))}${BOX_BR2}${toolResetSeq()}`;
|
|
597068
597141
|
}
|
|
597142
|
+
function dimSeqOrEmpty() {
|
|
597143
|
+
return _colorsEnabled && stdoutIsTTY() ? "\x1B[2m" : "";
|
|
597144
|
+
}
|
|
597145
|
+
function underlineSeqOrEmpty() {
|
|
597146
|
+
return _colorsEnabled && stdoutIsTTY() ? "\x1B[4m" : "";
|
|
597147
|
+
}
|
|
597148
|
+
function collapsedBarLine(desc) {
|
|
597149
|
+
const seq = toolColorSeq(desc.colorCode);
|
|
597150
|
+
const reset = toolResetSeq();
|
|
597151
|
+
const dim = dimSeqOrEmpty();
|
|
597152
|
+
const title = sanitizeToolBoxContent(desc.title);
|
|
597153
|
+
const metrics2 = desc.metrics ? ` ${dim}${sanitizeToolBoxContent(desc.metrics)}${reset}` : "";
|
|
597154
|
+
return `${seq}▸ ${title}${reset}${metrics2}`;
|
|
597155
|
+
}
|
|
597156
|
+
function affordanceRowText(label, hiddenRows) {
|
|
597157
|
+
const ul = underlineSeqOrEmpty();
|
|
597158
|
+
const dim = dimSeqOrEmpty();
|
|
597159
|
+
const reset = toolResetSeq();
|
|
597160
|
+
const suffix = hiddenRows && hiddenRows > 0 ? `${dim} (${hiddenRows} more line${hiddenRows === 1 ? "" : "s"})${reset}` : "";
|
|
597161
|
+
return `${ul}${label}${reset}${suffix}`;
|
|
597162
|
+
}
|
|
597163
|
+
function applyCollapseToBox(fullLines, opts) {
|
|
597164
|
+
if (fullLines.length === 0) return fullLines;
|
|
597165
|
+
if (opts.state === "collapsed") return [collapsedBarLine(opts.desc)];
|
|
597166
|
+
if (fullLines.length < 4) return fullLines;
|
|
597167
|
+
const w = Math.max(40, opts.width);
|
|
597168
|
+
const head = fullLines.slice(0, 2);
|
|
597169
|
+
const bottom = fullLines[fullLines.length - 1];
|
|
597170
|
+
const body = fullLines.slice(2, fullLines.length - 1);
|
|
597171
|
+
if (body.length <= PREVIEW_ROWS) return fullLines;
|
|
597172
|
+
if (opts.state === "preview") {
|
|
597173
|
+
const shown = body.slice(0, PREVIEW_ROWS);
|
|
597174
|
+
const moreRow = buildToolContentRow(
|
|
597175
|
+
affordanceRowText(READ_MORE_LABEL, body.length - PREVIEW_ROWS),
|
|
597176
|
+
w,
|
|
597177
|
+
opts.desc.colorCode
|
|
597178
|
+
);
|
|
597179
|
+
return [...head, ...shown, moreRow, bottom];
|
|
597180
|
+
}
|
|
597181
|
+
const lessRow = buildToolContentRow(
|
|
597182
|
+
affordanceRowText(READ_LESS_LABEL),
|
|
597183
|
+
w,
|
|
597184
|
+
opts.desc.colorCode
|
|
597185
|
+
);
|
|
597186
|
+
return [...head, ...body, lessRow, bottom];
|
|
597187
|
+
}
|
|
597069
597188
|
function buildToolContentRow(content, width, colorCode) {
|
|
597070
597189
|
const border = toolColorSeq(colorCode);
|
|
597071
597190
|
const reset = toolResetSeq();
|
|
@@ -597308,12 +597427,24 @@ function buildToolBoxLines(data, width) {
|
|
|
597308
597427
|
lines.push(buildToolBottom(w, data.colorCode));
|
|
597309
597428
|
return lines;
|
|
597310
597429
|
}
|
|
597311
|
-
function renderToolDynamicBlock(kind, render2, opts) {
|
|
597430
|
+
function renderToolDynamicBlock(kind, render2, opts, collapse) {
|
|
597312
597431
|
const redir = _contentWriteHook?.redirect?.();
|
|
597313
597432
|
const host = opts.host !== void 0 ? opts.host : _contentWriteHook?.dynamicBlockHost?.();
|
|
597314
597433
|
if (!redir && host) {
|
|
597315
597434
|
const id = `${kind}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
597316
|
-
|
|
597435
|
+
if (collapse) {
|
|
597436
|
+
ensureCollapsible(id);
|
|
597437
|
+
host.registerDynamicBlock(
|
|
597438
|
+
id,
|
|
597439
|
+
(width) => applyCollapseToBox(render2(width), {
|
|
597440
|
+
state: getCollapseState(id),
|
|
597441
|
+
desc: collapse,
|
|
597442
|
+
width
|
|
597443
|
+
})
|
|
597444
|
+
);
|
|
597445
|
+
} else {
|
|
597446
|
+
host.registerDynamicBlock(id, render2);
|
|
597447
|
+
}
|
|
597317
597448
|
host.appendDynamicBlock(id);
|
|
597318
597449
|
return;
|
|
597319
597450
|
}
|
|
@@ -597778,10 +597909,32 @@ function renderToolLine(content, isLast = false) {
|
|
|
597778
597909
|
process.stdout.write(`${lines.join("\n")}
|
|
597779
597910
|
`);
|
|
597780
597911
|
}
|
|
597912
|
+
function toolResultCollapseDescriptor(toolName, success, output, opts) {
|
|
597913
|
+
const label = TOOL_LABELS[toolName] ?? toolName;
|
|
597914
|
+
const status = success ? "✔" : "✖";
|
|
597915
|
+
const rawLines = output.split("\n").filter((line) => line.trim()).length;
|
|
597916
|
+
const metrics2 = [
|
|
597917
|
+
success ? "ok" : "failed",
|
|
597918
|
+
rawLines > 0 ? `${rawLines} line${rawLines === 1 ? "" : "s"}` : "",
|
|
597919
|
+
output.length > 0 ? `${output.length.toLocaleString()} chars` : "",
|
|
597920
|
+
opts.durationMs && opts.durationMs > 0 ? formatDuration4(opts.durationMs) : ""
|
|
597921
|
+
].filter(Boolean).join(" · ");
|
|
597922
|
+
return {
|
|
597923
|
+
title: `${status} ${label}`,
|
|
597924
|
+
metrics: metrics2,
|
|
597925
|
+
colorCode: success ? toolColorCode(toolName) : TOOL_ERROR_COLOR_CODE
|
|
597926
|
+
};
|
|
597927
|
+
}
|
|
597781
597928
|
function renderToolResult(toolName, success, output, verboseOrOpts) {
|
|
597782
597929
|
breakTelegramCoalesce();
|
|
597783
597930
|
const opts = normalizeToolOpts(verboseOrOpts);
|
|
597784
597931
|
const frozenOutput = getSecretRedactor().redactText(String(output ?? ""));
|
|
597932
|
+
const collapseDesc = toolResultCollapseDescriptor(
|
|
597933
|
+
toolName,
|
|
597934
|
+
success,
|
|
597935
|
+
frozenOutput,
|
|
597936
|
+
opts
|
|
597937
|
+
);
|
|
597785
597938
|
if (_pendingToolCall && _pendingToolCall.toolName === toolName) {
|
|
597786
597939
|
const pending2 = _pendingToolCall;
|
|
597787
597940
|
_pendingToolCall = null;
|
|
@@ -597795,7 +597948,8 @@ function renderToolResult(toolName, success, output, verboseOrOpts) {
|
|
|
597795
597948
|
{ ...opts, verbose: pending2.verbose ?? opts.verbose },
|
|
597796
597949
|
width
|
|
597797
597950
|
),
|
|
597798
|
-
opts
|
|
597951
|
+
opts,
|
|
597952
|
+
collapseDesc
|
|
597799
597953
|
);
|
|
597800
597954
|
return;
|
|
597801
597955
|
}
|
|
@@ -597803,7 +597957,8 @@ function renderToolResult(toolName, success, output, verboseOrOpts) {
|
|
|
597803
597957
|
renderToolDynamicBlock(
|
|
597804
597958
|
"tool-result",
|
|
597805
597959
|
(width) => buildToolResultBoxLines(toolName, success, frozenOutput, opts, width),
|
|
597806
|
-
opts
|
|
597960
|
+
opts,
|
|
597961
|
+
collapseDesc
|
|
597807
597962
|
);
|
|
597808
597963
|
}
|
|
597809
597964
|
function renderBoxedBlock(opts) {
|
|
@@ -598226,6 +598381,7 @@ var init_render = __esm({
|
|
|
598226
598381
|
init_syntax_highlight();
|
|
598227
598382
|
init_model_picker();
|
|
598228
598383
|
init_secret_redactor();
|
|
598384
|
+
init_tool_collapse_store();
|
|
598229
598385
|
c3 = {
|
|
598230
598386
|
bold: (t2) => ansi2("1", t2),
|
|
598231
598387
|
dim: (t2) => stdoutIsTTY() ? `${dimFg()}${t2}\x1B[0m` : t2,
|
|
@@ -605735,6 +605891,31 @@ function getLastTaskSummary(repoRoot) {
|
|
|
605735
605891
|
const clean5 = text2.replace(/^\[.*?\]\s*/, "").replace(/\s+/g, " ").trim();
|
|
605736
605892
|
return clean5.length > 40 ? clean5.slice(0, 37) + "..." : clean5;
|
|
605737
605893
|
}
|
|
605894
|
+
function cleanSessionHistoryDisplayLine(line) {
|
|
605895
|
+
return String(line || "").replace(/\x1B\[[0-9;]*[a-zA-Z]/g, "").replace(/^[>❯▹∙•*+\-\s]+/, "").replace(/^\[.*?\]\s*/, "").replace(/^(?:User|Assistant|You|Open Agent|Omnius)\s*:\s*/i, "").replace(/\s+/g, " ").trim();
|
|
605896
|
+
}
|
|
605897
|
+
function isNoisySessionHistoryLine(line) {
|
|
605898
|
+
const clean5 = cleanSessionHistoryDisplayLine(line || "");
|
|
605899
|
+
if (!clean5) return true;
|
|
605900
|
+
return /^(?:Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \/endpoint|Knowledge graph:|Zettelkasten:|Episodes captured:|Current OMNIUS_HOST:|Loaded TUI session|General session$|Chat tui:sess|i\s+)/i.test(clean5);
|
|
605901
|
+
}
|
|
605902
|
+
function firstMeaningfulSessionHistoryLine(lines) {
|
|
605903
|
+
for (const line of lines) {
|
|
605904
|
+
const clean5 = cleanSessionHistoryDisplayLine(line);
|
|
605905
|
+
if (!isNoisySessionHistoryLine(clean5)) return clean5;
|
|
605906
|
+
}
|
|
605907
|
+
return "";
|
|
605908
|
+
}
|
|
605909
|
+
function sanitizeSessionHistoryEntry(repoRoot, entry) {
|
|
605910
|
+
if (!isNoisySessionHistoryLine(entry.name) && !isNoisySessionHistoryLine(entry.description)) return entry;
|
|
605911
|
+
const lines = loadSessionHistory(repoRoot, entry.id) || [];
|
|
605912
|
+
const fallback = firstMeaningfulSessionHistoryLine(lines);
|
|
605913
|
+
return {
|
|
605914
|
+
...entry,
|
|
605915
|
+
name: isNoisySessionHistoryLine(entry.name) ? fallback ? fallback.length > 40 ? fallback.slice(0, 37) + "..." : fallback : entry.name : entry.name,
|
|
605916
|
+
description: isNoisySessionHistoryLine(entry.description) ? fallback || entry.description : entry.description
|
|
605917
|
+
};
|
|
605918
|
+
}
|
|
605738
605919
|
function saveSessionHistory(repoRoot, sessionId, contentLines, meta) {
|
|
605739
605920
|
const sessDir = join125(repoRoot, OMNIUS_DIR, SESSIONS_DIR);
|
|
605740
605921
|
mkdirSync66(sessDir, { recursive: true });
|
|
@@ -605782,7 +605963,7 @@ function listSessions(repoRoot) {
|
|
|
605782
605963
|
try {
|
|
605783
605964
|
if (!existsSync110(indexPath)) return [];
|
|
605784
605965
|
const index = JSON.parse(readFileSync89(indexPath, "utf-8"));
|
|
605785
|
-
return index.sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
|
|
605966
|
+
return index.map((entry) => sanitizeSessionHistoryEntry(repoRoot, entry)).sort((a2, b) => b.updatedAt.localeCompare(a2.updatedAt));
|
|
605786
605967
|
} catch {
|
|
605787
605968
|
return [];
|
|
605788
605969
|
}
|
|
@@ -605813,12 +605994,9 @@ function deleteSession(repoRoot, sessionId) {
|
|
|
605813
605994
|
}
|
|
605814
605995
|
}
|
|
605815
605996
|
function generateSessionName(lines) {
|
|
605816
|
-
|
|
605817
|
-
|
|
605818
|
-
|
|
605819
|
-
const phrase = clean5.replace(/^[>❯▹]\s*/, "").slice(0, 40);
|
|
605820
|
-
return phrase.length > 37 ? phrase.slice(0, 37) + "..." : phrase;
|
|
605821
|
-
}
|
|
605997
|
+
const phrase = firstMeaningfulSessionHistoryLine(lines.slice(0, 80));
|
|
605998
|
+
if (phrase.length > 10) {
|
|
605999
|
+
return phrase.length > 40 ? phrase.slice(0, 37) + "..." : phrase;
|
|
605822
606000
|
}
|
|
605823
606001
|
return `Session ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 10)}`;
|
|
605824
606002
|
}
|
|
@@ -605836,7 +606014,9 @@ function generateSessionDescription(lines) {
|
|
|
605836
606014
|
}
|
|
605837
606015
|
if (topics.length >= 3) break;
|
|
605838
606016
|
}
|
|
605839
|
-
|
|
606017
|
+
if (topics.length > 0) return topics.join(", ");
|
|
606018
|
+
const fallback = firstMeaningfulSessionHistoryLine(lines.slice(0, 120));
|
|
606019
|
+
return fallback || "General session";
|
|
605840
606020
|
}
|
|
605841
606021
|
function detectManifests(repoRoot) {
|
|
605842
606022
|
const manifests = [];
|
|
@@ -607403,6 +607583,25 @@ __export(status_bar_exports, {
|
|
|
607403
607583
|
unlockFooterRedraws: () => unlockFooterRedraws
|
|
607404
607584
|
});
|
|
607405
607585
|
import { readFileSync as readFileSync91 } from "node:fs";
|
|
607586
|
+
function headerButtonGlyphFg() {
|
|
607587
|
+
const a2 = tuiAccent();
|
|
607588
|
+
return a2 < 0 ? "\x1B[39m" : `\x1B[38;5;${a2}m`;
|
|
607589
|
+
}
|
|
607590
|
+
function headerButtonBg() {
|
|
607591
|
+
const a2 = tuiAccent();
|
|
607592
|
+
return a2 < 0 ? "\x1B[7m" : `\x1B[48;5;${a2}m`;
|
|
607593
|
+
}
|
|
607594
|
+
function headerButtonFg() {
|
|
607595
|
+
const a2 = tuiAccent();
|
|
607596
|
+
return a2 < 0 ? "" : `\x1B[38;5;${contrastTextColor(a2)}m`;
|
|
607597
|
+
}
|
|
607598
|
+
function headerAccentBoldFg() {
|
|
607599
|
+
const a2 = tuiAccent();
|
|
607600
|
+
return a2 < 0 ? "\x1B[1;39m" : `\x1B[1;38;5;${a2}m`;
|
|
607601
|
+
}
|
|
607602
|
+
function headerTelegramFg() {
|
|
607603
|
+
return themeMode() === "system" ? "\x1B[39m" : "\x1B[38;5;45m";
|
|
607604
|
+
}
|
|
607406
607605
|
function stripSubAgentPrefix(label) {
|
|
607407
607606
|
const stripped = label.replace(/^\s*sub[-\s]?agents?\b[\s:_–—-]*/i, "").trim();
|
|
607408
607607
|
return stripped.length > 0 ? stripped : label.trim();
|
|
@@ -607460,6 +607659,11 @@ function refreshThemeVars() {
|
|
|
607460
607659
|
BOX_FG = tuiBoxFg();
|
|
607461
607660
|
TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
|
|
607462
607661
|
TEXT_DIM = tuiTextDim();
|
|
607662
|
+
HEADER_BUTTON_GLYPH_FG = headerButtonGlyphFg();
|
|
607663
|
+
HEADER_BUTTON_BG = headerButtonBg();
|
|
607664
|
+
HEADER_BUTTON_FG = headerButtonFg();
|
|
607665
|
+
HEADER_ACCENT_BOLD_FG = headerAccentBoldFg();
|
|
607666
|
+
HEADER_TELEGRAM_FG = headerTelegramFg();
|
|
607463
607667
|
}
|
|
607464
607668
|
function sanitizeSponsorHeaderText(value2, max = SPONSOR_HEADER_LABEL_MAX) {
|
|
607465
607669
|
const cleaned = stripAnsi(String(value2 ?? "")).replace(/[\x00-\x1F\x7F]/g, " ").replace(/\s+/g, " ").trim();
|
|
@@ -607494,7 +607698,7 @@ function setTerminalTitle(task, version4) {
|
|
|
607494
607698
|
process.stdout.write(data);
|
|
607495
607699
|
}
|
|
607496
607700
|
}
|
|
607497
|
-
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL,
|
|
607701
|
+
var EXPERT_TOOL_BASELINES, CONTEXT_SWITCH_OVERHEAD, TURN_PLANNING_OVERHEAD, DEFAULT_TOOL_BASELINE, CODE_READ_CHARS_PER_SEC, PROSE_READ_CHARS_PER_SEC, MIN_CONTENT_FOR_READING, CODE_CONTENT_TOOLS, PROSE_CONTENT_TOOLS, HumanSpeedTracker, PANEL_BG_SEQ, CONTENT_BG_SEQ, BOX_FG, TEXT_PRIMARY, TEXT_DIM, NO_SUB_AGENTS_HEADER_LABEL, HEADER_BUTTON_GLYPH_FG, HEADER_BUTTON_BG, HEADER_BUTTON_FG, HEADER_ACCENT_BOLD_FG, HEADER_TELEGRAM_FG, BOX_TL3, BOX_TR3, BOX_BL3, BOX_BR3, BOX_H3, BOX_V3, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
|
|
607498
607702
|
var init_status_bar = __esm({
|
|
607499
607703
|
"packages/cli/src/tui/status-bar.ts"() {
|
|
607500
607704
|
"use strict";
|
|
@@ -607506,6 +607710,7 @@ var init_status_bar = __esm({
|
|
|
607506
607710
|
init_overlay_lock();
|
|
607507
607711
|
init_dist5();
|
|
607508
607712
|
init_theme();
|
|
607713
|
+
init_tool_collapse_store();
|
|
607509
607714
|
init_layout2();
|
|
607510
607715
|
EXPERT_TOOL_BASELINES = {
|
|
607511
607716
|
file_read: 12,
|
|
@@ -607674,10 +607879,11 @@ var init_status_bar = __esm({
|
|
|
607674
607879
|
TEXT_PRIMARY = tuiTextPrimary() < 0 ? 252 : tuiTextPrimary();
|
|
607675
607880
|
TEXT_DIM = tuiTextDim();
|
|
607676
607881
|
NO_SUB_AGENTS_HEADER_LABEL = " no agents ";
|
|
607677
|
-
|
|
607678
|
-
|
|
607679
|
-
|
|
607680
|
-
|
|
607882
|
+
HEADER_BUTTON_GLYPH_FG = headerButtonGlyphFg();
|
|
607883
|
+
HEADER_BUTTON_BG = headerButtonBg();
|
|
607884
|
+
HEADER_BUTTON_FG = headerButtonFg();
|
|
607885
|
+
HEADER_ACCENT_BOLD_FG = headerAccentBoldFg();
|
|
607886
|
+
HEADER_TELEGRAM_FG = headerTelegramFg();
|
|
607681
607887
|
BOX_TL3 = "╭";
|
|
607682
607888
|
BOX_TR3 = "╮";
|
|
607683
607889
|
BOX_BL3 = "╰";
|
|
@@ -607736,6 +607942,11 @@ var init_status_bar = __esm({
|
|
|
607736
607942
|
_contentScrollOffset = 0;
|
|
607737
607943
|
// 0 = live (bottom), >0 = scrolled back
|
|
607738
607944
|
_contentMaxLines = 1e4;
|
|
607945
|
+
// Snapshot of the most recent content paint, used to map a mouse-click screen
|
|
607946
|
+
// row back to the reflowed line (and thus its dynamic-block id) for click
|
|
607947
|
+
// hit-testing on collapsible tool boxes. Refreshed on every repaintContent().
|
|
607948
|
+
_lastPaintReflow = null;
|
|
607949
|
+
_lastPaintStartIdx = 0;
|
|
607739
607950
|
/**
|
|
607740
607951
|
* Dynamic content blocks — width-aware regions that re-render themselves
|
|
607741
607952
|
* when the terminal resizes. The renderer registered here is called from
|
|
@@ -608148,7 +608359,7 @@ var init_status_bar = __esm({
|
|
|
608148
608359
|
return fg2;
|
|
608149
608360
|
};
|
|
608150
608361
|
const decorateMenuButton = (cmd, label) => {
|
|
608151
|
-
return
|
|
608362
|
+
return `${HEADER_BUTTON_GLYPH_FG}🭁\x1B[0m${HEADER_BUTTON_BG}${HEADER_BUTTON_FG}${label}\x1B[0m${PANEL_BG_SEQ}${HEADER_BUTTON_GLYPH_FG}🭝\x1B[0m${PANEL_BG_SEQ}`;
|
|
608152
608363
|
};
|
|
608153
608364
|
const decorateAgentButton = (content, color, active) => {
|
|
608154
608365
|
const bg = `\x1B[48;5;${color}m`;
|
|
@@ -608282,7 +608493,7 @@ var init_status_bar = __esm({
|
|
|
608282
608493
|
sysItems.push({
|
|
608283
608494
|
render: () => renderBtn(
|
|
608284
608495
|
"telegram",
|
|
608285
|
-
|
|
608496
|
+
`${HEADER_TELEGRAM_FG}${telegramDot}${telegramLabel}\x1B[0m`
|
|
608286
608497
|
) + " ",
|
|
608287
608498
|
w: telegramLabel.length + 2
|
|
608288
608499
|
});
|
|
@@ -609442,6 +609653,55 @@ var init_status_bar = __esm({
|
|
|
609442
609653
|
get textSelection() {
|
|
609443
609654
|
return this._textSelection;
|
|
609444
609655
|
}
|
|
609656
|
+
/**
|
|
609657
|
+
* Map a screen row to the collapsible tool box painted there (if any). Uses
|
|
609658
|
+
* the snapshot captured during the last repaintContent(): screen row r shows
|
|
609659
|
+
* reflowedLines[startIdx + (r - scrollRegionTop)]. All reflowed rows of a
|
|
609660
|
+
* dynamic block share the sentinel's bufferIdx, so we can recover the block
|
|
609661
|
+
* id and the row's offset within the block.
|
|
609662
|
+
*/
|
|
609663
|
+
hitTestContentBlock(screenRow) {
|
|
609664
|
+
const reflow = this._lastPaintReflow;
|
|
609665
|
+
if (!reflow) return null;
|
|
609666
|
+
const rel = screenRow - this.scrollRegionTop;
|
|
609667
|
+
if (rel < 0) return null;
|
|
609668
|
+
const idx = this._lastPaintStartIdx + rel;
|
|
609669
|
+
const entry = reflow[idx];
|
|
609670
|
+
if (!entry) return null;
|
|
609671
|
+
const src2 = this._contentLines[entry.bufferIdx];
|
|
609672
|
+
if (!src2 || !src2.startsWith(this.DYNAMIC_BLOCK_MARK_PREFIX) || !src2.endsWith(this.DYNAMIC_BLOCK_MARK_SUFFIX)) {
|
|
609673
|
+
return null;
|
|
609674
|
+
}
|
|
609675
|
+
const id = src2.slice(
|
|
609676
|
+
this.DYNAMIC_BLOCK_MARK_PREFIX.length,
|
|
609677
|
+
src2.length - this.DYNAMIC_BLOCK_MARK_SUFFIX.length
|
|
609678
|
+
);
|
|
609679
|
+
let first2 = idx;
|
|
609680
|
+
while (first2 > 0 && reflow[first2 - 1]?.bufferIdx === entry.bufferIdx) {
|
|
609681
|
+
first2--;
|
|
609682
|
+
}
|
|
609683
|
+
return { id, offset: idx - first2, lineText: entry.line };
|
|
609684
|
+
}
|
|
609685
|
+
/**
|
|
609686
|
+
* Handle a click inside a collapsible tool box. Title row (offset 0) toggles
|
|
609687
|
+
* collapsed↔preview; a "read more…/read less" row toggles preview↔expanded;
|
|
609688
|
+
* other body rows are left alone so text selection still works. Returns true
|
|
609689
|
+
* when the click was consumed.
|
|
609690
|
+
*/
|
|
609691
|
+
handleContentBlockClick(screenRow) {
|
|
609692
|
+
const hit = this.hitTestContentBlock(screenRow);
|
|
609693
|
+
if (!hit || !isCollapsibleBlock(hit.id)) return false;
|
|
609694
|
+
const plain = stripAnsi(hit.lineText);
|
|
609695
|
+
if (plain.includes(READ_MORE_LABEL) || plain.includes(READ_LESS_LABEL)) {
|
|
609696
|
+
toggleMore(hit.id);
|
|
609697
|
+
} else if (hit.offset === 0) {
|
|
609698
|
+
toggleTitle(hit.id);
|
|
609699
|
+
} else {
|
|
609700
|
+
return false;
|
|
609701
|
+
}
|
|
609702
|
+
this.refreshDynamicBlocks();
|
|
609703
|
+
return true;
|
|
609704
|
+
}
|
|
609445
609705
|
/**
|
|
609446
609706
|
* Handle a mouse pointer event (press/drag/release).
|
|
609447
609707
|
* Called by MouseFilterStream's pointer handler.
|
|
@@ -609451,6 +609711,9 @@ var init_status_bar = __esm({
|
|
|
609451
609711
|
handlePointerEvent(type, col, row) {
|
|
609452
609712
|
if (!this.active) return;
|
|
609453
609713
|
const w = termCols();
|
|
609714
|
+
if (type === "press" && row >= this.scrollRegionTop) {
|
|
609715
|
+
if (this.handleContentBlockClick(row)) return;
|
|
609716
|
+
}
|
|
609454
609717
|
if (type === "press" && this._suggestions.length > 0) {
|
|
609455
609718
|
if (this.suggestClickAt(row)) return;
|
|
609456
609719
|
}
|
|
@@ -610103,6 +610366,20 @@ ${CONTENT_BG_SEQ}`);
|
|
|
610103
610366
|
this.repaintContent();
|
|
610104
610367
|
this.renderFooterAndPositionInput();
|
|
610105
610368
|
}
|
|
610369
|
+
/**
|
|
610370
|
+
* Flicker-free in-place repaint of the content area (and thus any dynamic
|
|
610371
|
+
* blocks within it). Unlike refreshDisplay(), this does NOT blank the area
|
|
610372
|
+
* first via fillContentArea() — repaintContent() uses synchronized output
|
|
610373
|
+
* (\x1B[?2026h) and a per-row \x1B[2K clear, so a live block that updates
|
|
610374
|
+
* many times per second (e.g. the shell timer) refreshes without the whole
|
|
610375
|
+
* TUI flashing. Implements the DynamicBlockHost.refreshDynamicBlocks contract.
|
|
610376
|
+
*/
|
|
610377
|
+
refreshDynamicBlocks() {
|
|
610378
|
+
if (!this.active) return;
|
|
610379
|
+
if (this._contentScrollOffset > 0 || this._mouseSelecting) return;
|
|
610380
|
+
if (isOverlayActive() || this._suspendContentLayer) return;
|
|
610381
|
+
this.repaintContent();
|
|
610382
|
+
}
|
|
610106
610383
|
clearStreamingRepaintTimer() {
|
|
610107
610384
|
if (!this._streamingRepaintTimer) return;
|
|
610108
610385
|
clearTimeout(this._streamingRepaintTimer);
|
|
@@ -610481,6 +610758,8 @@ ${CONTENT_BG_SEQ}`);
|
|
|
610481
610758
|
if (this._contentScrollOffset === 0) this._autoScroll = true;
|
|
610482
610759
|
}
|
|
610483
610760
|
const startIdx = Math.max(0, totalLines - h - this._contentScrollOffset);
|
|
610761
|
+
this._lastPaintReflow = reflowedLines;
|
|
610762
|
+
this._lastPaintStartIdx = startIdx;
|
|
610484
610763
|
const headerSafeFloor = layout().headerBottom + 1;
|
|
610485
610764
|
let buf = "\x1B[?2026h";
|
|
610486
610765
|
buf += "\x1B7";
|
|
@@ -610719,8 +610998,8 @@ ${CONTENT_BG_SEQ}`);
|
|
|
610719
610998
|
const label = `✈ tg${suffix}`;
|
|
610720
610999
|
const compact3 = `✈${suffix}`;
|
|
610721
611000
|
sections.push({
|
|
610722
|
-
expanded:
|
|
610723
|
-
compact:
|
|
611001
|
+
expanded: `${HEADER_TELEGRAM_FG}${label}\x1B[0m`,
|
|
611002
|
+
compact: `${HEADER_TELEGRAM_FG}${compact3}\x1B[0m`,
|
|
610724
611003
|
expandedW: 2 + 3 + suffix.length,
|
|
610725
611004
|
compactW: 2 + suffix.length,
|
|
610726
611005
|
empty: false,
|
|
@@ -645238,22 +645517,51 @@ function normalizeRoot(root) {
|
|
|
645238
645517
|
}
|
|
645239
645518
|
}
|
|
645240
645519
|
function stripAnsi5(text2) {
|
|
645241
|
-
return String(text2 || "").replace(
|
|
645520
|
+
return String(text2 || "").replace(/\u001b\[[0-9;]*[a-zA-Z]/g, "");
|
|
645521
|
+
}
|
|
645522
|
+
function cleanSessionDisplayLine(line) {
|
|
645523
|
+
return stripAnsi5(line).replace(/^[>❯▹∙•*+\-\s]+/, "").replace(/^(?:User|Assistant|You|Open Agent|Omnius)\s*:\s*/i, "").replace(/\s+/g, " ").trim();
|
|
645524
|
+
}
|
|
645525
|
+
function isNoisySessionDisplayLine(line) {
|
|
645526
|
+
const clean5 = cleanSessionDisplayLine(line || "");
|
|
645527
|
+
if (!clean5) return true;
|
|
645528
|
+
return /^(?:Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \/endpoint|Knowledge graph:|Zettelkasten:|Episodes captured:|Current OMNIUS_HOST:|Loaded TUI session|General session$|Chat tui:sess|\[Imported TUI session transcript\]|Title:|Description:|Project root:|i\s+)/i.test(clean5);
|
|
645529
|
+
}
|
|
645530
|
+
function bestSessionDisplayLine(text2) {
|
|
645531
|
+
const lines = stripAnsi5(text2).split(/\r?\n/);
|
|
645532
|
+
for (const line of lines) {
|
|
645533
|
+
const clean5 = cleanSessionDisplayLine(line);
|
|
645534
|
+
if (!isNoisySessionDisplayLine(clean5)) return clean5;
|
|
645535
|
+
}
|
|
645536
|
+
const fallback = stripAnsi5(text2).replace(/\s+/g, " ").trim();
|
|
645537
|
+
return isNoisySessionDisplayLine(fallback) ? "" : fallback;
|
|
645242
645538
|
}
|
|
645243
645539
|
function makeTitle(text2) {
|
|
645244
|
-
const clean5 =
|
|
645540
|
+
const clean5 = bestSessionDisplayLine(text2);
|
|
645245
645541
|
if (!clean5) return "Chat session";
|
|
645246
|
-
return clean5.length > 72 ?
|
|
645542
|
+
return clean5.length > 72 ? clean5.slice(0, 69) + "..." : clean5;
|
|
645247
645543
|
}
|
|
645248
645544
|
function makePreview(text2) {
|
|
645249
|
-
const clean5 =
|
|
645250
|
-
return clean5.length > 160 ?
|
|
645545
|
+
const clean5 = bestSessionDisplayLine(text2);
|
|
645546
|
+
return clean5.length > 160 ? clean5.slice(0, 157) + "..." : clean5;
|
|
645251
645547
|
}
|
|
645252
645548
|
function normalizeLoadedSession(parsed) {
|
|
645253
645549
|
if (!parsed.source) parsed.source = "web";
|
|
645254
645550
|
if (parsed.projectRoot) parsed.projectRoot = normalizeRoot(parsed.projectRoot);
|
|
645551
|
+
if (parsed.title && isNoisySessionDisplayLine(parsed.title)) parsed.title = void 0;
|
|
645552
|
+
if (parsed.preview && isNoisySessionDisplayLine(parsed.preview)) parsed.preview = "";
|
|
645553
|
+
const importedContext = (parsed.messages || []).find(
|
|
645554
|
+
(m2) => m2.role === "system" && m2.content.startsWith("[Imported TUI session transcript]")
|
|
645555
|
+
)?.content;
|
|
645556
|
+
if ((parsed.source === "tui" || parsed.id?.startsWith("tui:")) && importedContext) {
|
|
645557
|
+
const importedPreview = makePreview(importedContext);
|
|
645558
|
+
if (!parsed.preview && importedPreview) parsed.preview = importedPreview;
|
|
645559
|
+
if (!parsed.title && importedPreview) parsed.title = makeTitle(importedPreview);
|
|
645560
|
+
}
|
|
645255
645561
|
if (!parsed.preview) {
|
|
645256
|
-
const last2 = [...parsed.messages || []].reverse().find(
|
|
645562
|
+
const last2 = [...parsed.messages || []].reverse().find(
|
|
645563
|
+
(m2) => (m2.role === "user" || m2.role === "assistant") && !isNoisySessionDisplayLine(m2.content)
|
|
645564
|
+
);
|
|
645257
645565
|
parsed.preview = last2 ? makePreview(last2.content) : "";
|
|
645258
645566
|
}
|
|
645259
645567
|
if (!parsed.title && parsed.preview) parsed.title = makeTitle(parsed.preview);
|
|
@@ -645426,9 +645734,10 @@ function getSession2(sessionId, model, cwd4) {
|
|
|
645426
645734
|
function importTranscriptSession(opts) {
|
|
645427
645735
|
const projectRoot = normalizeRoot(opts.projectRoot) ?? process.cwd();
|
|
645428
645736
|
const id = opts.id;
|
|
645429
|
-
const title = opts.title || makeTitle(opts.description || id);
|
|
645430
|
-
const preview = makePreview(opts.description || opts.transcriptLines.slice(-8).join(" "));
|
|
645431
645737
|
const transcript = opts.transcriptLines.map(stripAnsi5).join("\n").trim();
|
|
645738
|
+
const metadataSource = [opts.title, opts.description, transcript].filter(Boolean).join("\n");
|
|
645739
|
+
const title = makeTitle(metadataSource || id);
|
|
645740
|
+
const preview = makePreview([opts.description, transcript].filter(Boolean).join("\n") || title);
|
|
645432
645741
|
const cappedTranscript = transcript.length > 32e3 ? `[earlier transcript truncated: ${transcript.length - 32e3} chars]
|
|
645433
645742
|
` + transcript.slice(-32e3) : transcript;
|
|
645434
645743
|
const importedContext = [
|
|
@@ -653186,8 +653495,8 @@ var init_telegram_stats_menu = __esm({
|
|
|
653186
653495
|
INACTIVITY_TIMEOUT_MS2 = 6e4;
|
|
653187
653496
|
COUNTDOWN_SECONDS2 = 10;
|
|
653188
653497
|
StatsMenuTimerManager = class {
|
|
653189
|
-
constructor(
|
|
653190
|
-
this.states =
|
|
653498
|
+
constructor(states2, callbacks, getSnapshot) {
|
|
653499
|
+
this.states = states2;
|
|
653191
653500
|
this.callbacks = callbacks;
|
|
653192
653501
|
this.getSnapshot = getSnapshot;
|
|
653193
653502
|
}
|
|
@@ -668170,9 +668479,9 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
668170
668479
|
}
|
|
668171
668480
|
createTelegramGenerativeProgressBridge(chatId, msg) {
|
|
668172
668481
|
if (chatId === void 0) return void 0;
|
|
668173
|
-
const
|
|
668482
|
+
const states2 = /* @__PURE__ */ new Map();
|
|
668174
668483
|
const stateFor = (toolName) => {
|
|
668175
|
-
let state =
|
|
668484
|
+
let state = states2.get(toolName);
|
|
668176
668485
|
if (!state) {
|
|
668177
668486
|
state = {
|
|
668178
668487
|
messageId: null,
|
|
@@ -668180,7 +668489,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
668180
668489
|
queuedHtml: null,
|
|
668181
668490
|
lastRenderedAt: 0
|
|
668182
668491
|
};
|
|
668183
|
-
|
|
668492
|
+
states2.set(toolName, state);
|
|
668184
668493
|
}
|
|
668185
668494
|
return state;
|
|
668186
668495
|
};
|
|
@@ -668253,7 +668562,7 @@ ${TELEGRAM_PUBLIC_ORCHESTRATOR_CONTRACT}`
|
|
|
668253
668562
|
},
|
|
668254
668563
|
complete: (toolName, result) => {
|
|
668255
668564
|
if (!generationKindForToolName(toolName)) return;
|
|
668256
|
-
const state =
|
|
668565
|
+
const state = states2.get(toolName);
|
|
668257
668566
|
if (!state && result.success) return;
|
|
668258
668567
|
const html = completeHtml(toolName, result);
|
|
668259
668568
|
if (!html) return;
|
|
@@ -675638,6 +675947,10 @@ function finishShellLiveBlock(state, success) {
|
|
|
675638
675947
|
}
|
|
675639
675948
|
state.status = success ? "ok" : "failed";
|
|
675640
675949
|
}
|
|
675950
|
+
function shellLiveBlockFingerprint(state) {
|
|
675951
|
+
const sec = Math.floor(Math.max(0, Date.now() - state.startedAt) / 1e3);
|
|
675952
|
+
return `${state.status}|${state.lines.length}|${state.currentLine.length}|${sec}`;
|
|
675953
|
+
}
|
|
675641
675954
|
function buildShellLiveBlockLines(state, width) {
|
|
675642
675955
|
const w = Math.max(36, width);
|
|
675643
675956
|
const inner = Math.max(1, w - 4);
|
|
@@ -677678,6 +677991,10 @@ var init_direct_input = __esm({
|
|
|
677678
677991
|
this._deleteWordLeft();
|
|
677679
677992
|
return;
|
|
677680
677993
|
case 21:
|
|
677994
|
+
if (this.line.length === 0) {
|
|
677995
|
+
this.emit("ctrl-u");
|
|
677996
|
+
return;
|
|
677997
|
+
}
|
|
677681
677998
|
this.line = this.line.slice(this.cursor);
|
|
677682
677999
|
this.cursor = 0;
|
|
677683
678000
|
return;
|
|
@@ -681396,20 +681713,20 @@ async function handleNexusStatus(ctx3) {
|
|
|
681396
681713
|
join163(process.cwd(), ".omnius", "nexus-peer-state.json"),
|
|
681397
681714
|
join163(homedir56(), ".omnius", "nexus-peer-cache.json")
|
|
681398
681715
|
];
|
|
681399
|
-
const
|
|
681716
|
+
const states2 = [];
|
|
681400
681717
|
for (const p2 of statePaths) {
|
|
681401
681718
|
if (!existsSync151(p2)) continue;
|
|
681402
681719
|
try {
|
|
681403
681720
|
const raw = readFileSync123(p2, "utf-8");
|
|
681404
|
-
|
|
681721
|
+
states2.push({ source: p2, data: JSON.parse(raw) });
|
|
681405
681722
|
} catch (e2) {
|
|
681406
|
-
|
|
681723
|
+
states2.push({ source: p2, error: String(e2) });
|
|
681407
681724
|
}
|
|
681408
681725
|
}
|
|
681409
681726
|
const config = loadConfig();
|
|
681410
681727
|
sendJson2(res, 200, {
|
|
681411
|
-
connected:
|
|
681412
|
-
peer_cache_files:
|
|
681728
|
+
connected: states2.length > 0,
|
|
681729
|
+
peer_cache_files: states2,
|
|
681413
681730
|
agent_name: loadAgentName(),
|
|
681414
681731
|
backend_url: config.backendUrl
|
|
681415
681732
|
});
|
|
@@ -684599,6 +684916,100 @@ body { display:flex; flex-direction:column; height:100vh; margin:0; overflow:hid
|
|
|
684599
684916
|
border-color: var(--color-border-strong);
|
|
684600
684917
|
}
|
|
684601
684918
|
|
|
684919
|
+
.settings-provider-module-grid {
|
|
684920
|
+
display: grid;
|
|
684921
|
+
grid-template-columns: repeat(auto-fit, minmax(156px, 1fr));
|
|
684922
|
+
gap: 10px;
|
|
684923
|
+
}
|
|
684924
|
+
.settings-provider-module {
|
|
684925
|
+
min-height: 118px;
|
|
684926
|
+
border: 1px solid var(--color-border);
|
|
684927
|
+
border-radius: 8px;
|
|
684928
|
+
background: var(--color-bg-input);
|
|
684929
|
+
color: var(--color-fg);
|
|
684930
|
+
display: grid;
|
|
684931
|
+
align-content: center;
|
|
684932
|
+
justify-items: center;
|
|
684933
|
+
gap: 7px;
|
|
684934
|
+
padding: 12px;
|
|
684935
|
+
text-align: center;
|
|
684936
|
+
font: inherit;
|
|
684937
|
+
cursor: pointer;
|
|
684938
|
+
}
|
|
684939
|
+
.settings-provider-module:hover {
|
|
684940
|
+
background: var(--color-bg-hover);
|
|
684941
|
+
border-color: var(--color-border-strong);
|
|
684942
|
+
}
|
|
684943
|
+
.settings-provider-module.active {
|
|
684944
|
+
border-color: var(--color-brand);
|
|
684945
|
+
box-shadow: 0 0 0 1px color-mix(in srgb, var(--color-brand) 45%, transparent);
|
|
684946
|
+
}
|
|
684947
|
+
.settings-provider-brand {
|
|
684948
|
+
width: 34px;
|
|
684949
|
+
height: 34px;
|
|
684950
|
+
border-radius: 8px;
|
|
684951
|
+
border: 1px solid var(--color-border);
|
|
684952
|
+
background: var(--color-bg);
|
|
684953
|
+
display: inline-grid;
|
|
684954
|
+
place-items: center;
|
|
684955
|
+
overflow: hidden;
|
|
684956
|
+
color: var(--color-brand);
|
|
684957
|
+
font-weight: 700;
|
|
684958
|
+
}
|
|
684959
|
+
.settings-provider-brand img {
|
|
684960
|
+
width: 22px;
|
|
684961
|
+
height: 22px;
|
|
684962
|
+
object-fit: contain;
|
|
684963
|
+
}
|
|
684964
|
+
.settings-provider-module strong {
|
|
684965
|
+
font-size: 0.78rem;
|
|
684966
|
+
font-weight: 700;
|
|
684967
|
+
max-width: 100%;
|
|
684968
|
+
overflow-wrap: anywhere;
|
|
684969
|
+
}
|
|
684970
|
+
.settings-provider-module small {
|
|
684971
|
+
color: var(--color-fg-muted);
|
|
684972
|
+
font-size: 0.68rem;
|
|
684973
|
+
line-height: 1.25;
|
|
684974
|
+
}
|
|
684975
|
+
.settings-provider-setup {
|
|
684976
|
+
border: 1px solid var(--color-border);
|
|
684977
|
+
border-radius: 8px;
|
|
684978
|
+
background: var(--color-bg-elevated);
|
|
684979
|
+
padding: 12px;
|
|
684980
|
+
display: grid;
|
|
684981
|
+
gap: 10px;
|
|
684982
|
+
}
|
|
684983
|
+
.settings-provider-setup-head {
|
|
684984
|
+
display: grid;
|
|
684985
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
684986
|
+
gap: 10px;
|
|
684987
|
+
align-items: center;
|
|
684988
|
+
}
|
|
684989
|
+
.settings-provider-setup-head strong {
|
|
684990
|
+
display: block;
|
|
684991
|
+
font-size: 0.82rem;
|
|
684992
|
+
}
|
|
684993
|
+
.settings-provider-setup-head small,
|
|
684994
|
+
.settings-provider-meta {
|
|
684995
|
+
color: var(--color-fg-muted);
|
|
684996
|
+
font-size: 0.7rem;
|
|
684997
|
+
}
|
|
684998
|
+
.settings-provider-actions {
|
|
684999
|
+
display: flex;
|
|
685000
|
+
gap: 8px;
|
|
685001
|
+
align-items: center;
|
|
685002
|
+
flex-wrap: wrap;
|
|
685003
|
+
}
|
|
685004
|
+
.settings-provider-link {
|
|
685005
|
+
color: var(--color-brand);
|
|
685006
|
+
border: 1px solid var(--color-border);
|
|
685007
|
+
border-radius: var(--radius-sm);
|
|
685008
|
+
padding: 4px 8px;
|
|
685009
|
+
text-decoration: none;
|
|
685010
|
+
font-size: 0.7rem;
|
|
685011
|
+
}
|
|
685012
|
+
|
|
684602
685013
|
/* Settings models list rows */
|
|
684603
685014
|
#settings-models-list .row,
|
|
684604
685015
|
#mm-list .row {
|
|
@@ -685298,8 +685709,8 @@ body { display:flex; flex-direction:column; height:100vh; margin:0; overflow:hid
|
|
|
685298
685709
|
</label>
|
|
685299
685710
|
</section>
|
|
685300
685711
|
<section class="settings-pane" id="settings-pane-connections" role="tabpanel" hidden>
|
|
685301
|
-
<h4>
|
|
685302
|
-
<p style="font-size:0.74rem;color:var(--color-fg-muted);margin:6px 0 12px">
|
|
685712
|
+
<h4>Inference providers</h4>
|
|
685713
|
+
<p style="font-size:0.74rem;color:var(--color-fg-muted);margin:6px 0 12px">Choose a provider module, add auth when needed, then save it to the daemon endpoint.</p>
|
|
685303
685714
|
<div id="settings-connections-host">
|
|
685304
685715
|
<button onclick="loadSettingsConnections()" style="font-size:0.74rem">load current</button>
|
|
685305
685716
|
</div>
|
|
@@ -685535,6 +685946,44 @@ async function loadServerPrefs() {
|
|
|
685535
685946
|
} catch { return null; }
|
|
685536
685947
|
}
|
|
685537
685948
|
|
|
685949
|
+
function isNoisyChatSessionText(text) {
|
|
685950
|
+
const clean = String(text || '').replace(/\\s+/g, ' ').trim();
|
|
685951
|
+
if (!clean) return true;
|
|
685952
|
+
const t = clean.replace(/^[>❯▹∙•\\-\\s]+/, '');
|
|
685953
|
+
return /^(Previous session found|REST API:|Nexus P2P network connected|No context to restore|Starting fresh|Use \\/endpoint|General session$|Loaded TUI session|Chat tui:sess)/i.test(t);
|
|
685954
|
+
}
|
|
685955
|
+
|
|
685956
|
+
function isGenericChatTitle(id, title) {
|
|
685957
|
+
const t = String(title || '').trim();
|
|
685958
|
+
if (!t) return true;
|
|
685959
|
+
if (isNoisyChatSessionText(t)) return true;
|
|
685960
|
+
if (t === 'Chat ' + String(id || '').slice(0, 8)) return true;
|
|
685961
|
+
return /^Chat tui:sess/i.test(t);
|
|
685962
|
+
}
|
|
685963
|
+
|
|
685964
|
+
function sessionDisplayTitle(id, session) {
|
|
685965
|
+
const s = session || {};
|
|
685966
|
+
for (const candidate of [s.title, s.name, s.preview]) {
|
|
685967
|
+
if (!isGenericChatTitle(id, candidate)) return String(candidate).trim();
|
|
685968
|
+
}
|
|
685969
|
+
if (Array.isArray(s.messages)) {
|
|
685970
|
+
for (let i = s.messages.length - 1; i >= 0; i--) {
|
|
685971
|
+
const msg = s.messages[i];
|
|
685972
|
+
const content = msg && typeof msg.content === 'string' ? msg.content : '';
|
|
685973
|
+
if (!isGenericChatTitle(id, content)) return content.replace(/\\s+/g, ' ').trim().slice(0, 72);
|
|
685974
|
+
}
|
|
685975
|
+
}
|
|
685976
|
+
return String(id || '').startsWith('tui:') ? 'TUI session ' + String(id).slice(4, 16) : 'Chat ' + String(id || '').slice(0, 8);
|
|
685977
|
+
}
|
|
685978
|
+
|
|
685979
|
+
function sessionDisplayPreview(session) {
|
|
685980
|
+
const s = session || {};
|
|
685981
|
+
for (const candidate of [s.preview, s.title, s.name]) {
|
|
685982
|
+
if (!isNoisyChatSessionText(candidate)) return String(candidate).trim();
|
|
685983
|
+
}
|
|
685984
|
+
return '';
|
|
685985
|
+
}
|
|
685986
|
+
|
|
685538
685987
|
async function loadServerChatSessions() {
|
|
685539
685988
|
const root = $currentProject.get()?.root || '';
|
|
685540
685989
|
if (!root) return;
|
|
@@ -685547,16 +685996,24 @@ async function loadServerChatSessions() {
|
|
|
685547
685996
|
for (const sess of (data.sessions || [])) {
|
|
685548
685997
|
if (!sess || !sess.id) continue;
|
|
685549
685998
|
const existing = merged[sess.id] || {};
|
|
685999
|
+
const serverTitle = sess.title || sess.preview || '';
|
|
686000
|
+
const existingTitle = existing.title || existing.name || '';
|
|
686001
|
+
const title = !isGenericChatTitle(sess.id, existingTitle)
|
|
686002
|
+
? existingTitle
|
|
686003
|
+
: (!isGenericChatTitle(sess.id, serverTitle) ? serverTitle : sessionDisplayTitle(sess.id, sess));
|
|
686004
|
+
const preview = !isNoisyChatSessionText(existing.preview)
|
|
686005
|
+
? existing.preview
|
|
686006
|
+
: (!isNoisyChatSessionText(sess.preview) ? sess.preview : sessionDisplayPreview(sess));
|
|
685550
686007
|
merged[sess.id] = {
|
|
685551
686008
|
...existing,
|
|
685552
686009
|
id: sess.id,
|
|
685553
|
-
title
|
|
685554
|
-
name: existing.name
|
|
685555
|
-
preview
|
|
686010
|
+
title,
|
|
686011
|
+
name: !isGenericChatTitle(sess.id, existing.name) ? existing.name : title,
|
|
686012
|
+
preview,
|
|
685556
686013
|
model: existing.model || sess.model || '',
|
|
685557
686014
|
source: sess.source || existing.source || 'web',
|
|
685558
686015
|
projectRoot: sess.projectRoot || root,
|
|
685559
|
-
updatedAt:
|
|
686016
|
+
updatedAt: sess.lastActivity || sess.updatedAt || existing.updatedAt || '',
|
|
685560
686017
|
messages: existing.messages || [],
|
|
685561
686018
|
};
|
|
685562
686019
|
}
|
|
@@ -686085,6 +686542,7 @@ function addMessage(role, content) {
|
|
|
686085
686542
|
}
|
|
686086
686543
|
if (role === 'assistant' || (role === 'user' && looksLikeMarkdown(content))) {
|
|
686087
686544
|
host.innerHTML = renderMarkdown(content);
|
|
686545
|
+
appendArtifactsForText(host, content);
|
|
686088
686546
|
} else {
|
|
686089
686547
|
host.textContent = content;
|
|
686090
686548
|
}
|
|
@@ -686380,6 +686838,7 @@ function renderToolCallEvent(parent, chunkLike) {
|
|
|
686380
686838
|
argsDiv.appendChild(row);
|
|
686381
686839
|
}
|
|
686382
686840
|
}
|
|
686841
|
+
appendArtifactControls(argsDiv, extractArtifactsFromValue(a));
|
|
686383
686842
|
details.appendChild(argsDiv);
|
|
686384
686843
|
}
|
|
686385
686844
|
parent.appendChild(details);
|
|
@@ -686396,6 +686855,7 @@ function renderToolResultEvent(parent, chunkLike) {
|
|
|
686396
686855
|
: 'background:var(--color-bg-elevated);color:var(--color-fg-muted);';
|
|
686397
686856
|
resultEl.style.cssText = errStyle + 'padding:4px 8px 4px 18px;margin:0 0 2px 0;font-size:0.65rem';
|
|
686398
686857
|
appendExpandableContent(resultEl, chunkLike.output || '', { truncateAt: 150, baseStyle: 'color:inherit;' });
|
|
686858
|
+
appendArtifactControls(resultEl, extractArtifactsFromValue(chunkLike));
|
|
686399
686859
|
parent.appendChild(resultEl);
|
|
686400
686860
|
return resultEl;
|
|
686401
686861
|
}
|
|
@@ -686751,6 +687211,7 @@ async function sendMessage() {
|
|
|
686751
687211
|
fullContent += summaryText;
|
|
686752
687212
|
}
|
|
686753
687213
|
contentDiv.innerHTML = renderMarkdown(fullContent);
|
|
687214
|
+
appendArtifactsForText(contentDiv, fullContent);
|
|
686754
687215
|
hideStreamingIndicator(msgDiv);
|
|
686755
687216
|
maybeAutoScroll();
|
|
686756
687217
|
}
|
|
@@ -686862,6 +687323,7 @@ async function sendMessage() {
|
|
|
686862
687323
|
argsDiv.appendChild(row);
|
|
686863
687324
|
}
|
|
686864
687325
|
}
|
|
687326
|
+
appendArtifactControls(argsDiv, extractArtifactsFromValue(a));
|
|
686865
687327
|
details.appendChild(argsDiv);
|
|
686866
687328
|
}
|
|
686867
687329
|
toolsContainer.appendChild(details);
|
|
@@ -686874,10 +687336,8 @@ async function sendMessage() {
|
|
|
686874
687336
|
// 150 chars. The button sits underneath the result block.
|
|
686875
687337
|
if (chunk.type === 'tool_result') {
|
|
686876
687338
|
if (isInternalChatTool(chunk.tool || '')) continue;
|
|
686877
|
-
|
|
686878
|
-
|
|
686879
|
-
appendExpandableContent(resultEl, chunk.output || '', { truncateAt: 150, baseStyle: 'color:var(--color-fg-muted);' });
|
|
686880
|
-
toolsContainer.appendChild(resultEl);
|
|
687339
|
+
renderToolResultEvent(toolsContainer, chunk);
|
|
687340
|
+
maybeAutoScroll();
|
|
686881
687341
|
continue;
|
|
686882
687342
|
}
|
|
686883
687343
|
|
|
@@ -686893,6 +687353,7 @@ async function sendMessage() {
|
|
|
686893
687353
|
hideStreamingIndicator(msgDiv);
|
|
686894
687354
|
fullContent += delta;
|
|
686895
687355
|
contentDiv.innerHTML = renderMarkdown(fullContent);
|
|
687356
|
+
appendArtifactsForText(contentDiv, fullContent);
|
|
686896
687357
|
try { _highlightCodeBlocks(contentDiv); } catch {}
|
|
686897
687358
|
maybeAutoScroll();
|
|
686898
687359
|
}
|
|
@@ -686916,6 +687377,7 @@ async function sendMessage() {
|
|
|
686916
687377
|
|
|
686917
687378
|
// Final render: content + collapsible tools + metadata
|
|
686918
687379
|
contentDiv.innerHTML = renderMarkdown(fullContent);
|
|
687380
|
+
appendArtifactsForText(contentDiv, fullContent);
|
|
686919
687381
|
// OWUI-3: streaming complete — drop the pulsing dot.
|
|
686920
687382
|
hideStreamingIndicator(msgDiv);
|
|
686921
687383
|
try { _highlightCodeBlocks(contentDiv); } catch {}
|
|
@@ -688828,12 +689290,20 @@ async function loadJobs() {
|
|
|
688828
689290
|
function saveSessions() {
|
|
688829
689291
|
const saved = loadScopedSessions();
|
|
688830
689292
|
if (chatSessionId) {
|
|
689293
|
+
const existing = saved[chatSessionId] || (($chatSessions.get && $chatSessions.get()) || {})[chatSessionId] || {};
|
|
689294
|
+
const preview = messages.slice(-1)[0]?.content?.slice(0, 50) || sessionDisplayPreview(existing) || 'empty';
|
|
689295
|
+
const title = !isGenericChatTitle(chatSessionId, existing.title || existing.name)
|
|
689296
|
+
? (existing.title || existing.name)
|
|
689297
|
+
: sessionDisplayTitle(chatSessionId, { ...existing, preview, messages });
|
|
688831
689298
|
saved[chatSessionId] = {
|
|
689299
|
+
...existing,
|
|
688832
689300
|
id: chatSessionId,
|
|
689301
|
+
title,
|
|
689302
|
+
name: !isGenericChatTitle(chatSessionId, existing.name) ? existing.name : title,
|
|
688833
689303
|
messages: messages,
|
|
688834
689304
|
model: modelSelect.value,
|
|
688835
689305
|
updatedAt: new Date().toISOString(),
|
|
688836
|
-
preview
|
|
689306
|
+
preview,
|
|
688837
689307
|
};
|
|
688838
689308
|
}
|
|
688839
689309
|
saveScopedSessions(saved);
|
|
@@ -688859,7 +689329,7 @@ function updateSessionSelect() {
|
|
|
688859
689329
|
for (const [id, s] of entries) {
|
|
688860
689330
|
const opt = document.createElement('option');
|
|
688861
689331
|
opt.value = id;
|
|
688862
|
-
opt.textContent = (s
|
|
689332
|
+
opt.textContent = sessionDisplayTitle(id, s).slice(0, 40);
|
|
688863
689333
|
if (id === chatSessionId) opt.selected = true;
|
|
688864
689334
|
sel.appendChild(opt);
|
|
688865
689335
|
}
|
|
@@ -689668,6 +690138,255 @@ function rawFileUrl(path) {
|
|
|
689668
690138
|
return '/v1/files/raw?path=' + encodeURIComponent(path);
|
|
689669
690139
|
}
|
|
689670
690140
|
|
|
690141
|
+
function cleanArtifactPathCandidate(value) {
|
|
690142
|
+
let s = String(value || '').trim();
|
|
690143
|
+
s = s.replace(/^["'(<]+/, '').replace(/[)"'>,.;:]+$/, '');
|
|
690144
|
+
return s;
|
|
690145
|
+
}
|
|
690146
|
+
|
|
690147
|
+
function isPreviewableArtifactInfo(info) {
|
|
690148
|
+
return info && (info.kind === 'audio' || info.kind === 'video' || info.kind === 'image' || info.kind === 'pdf' || isTextPreviewable(info));
|
|
690149
|
+
}
|
|
690150
|
+
|
|
690151
|
+
function mediaUrlForStoredPath(path) {
|
|
690152
|
+
const normalized = String(path || '').split(String.fromCharCode(92)).join('/');
|
|
690153
|
+
const marker = '/.omnius/media/';
|
|
690154
|
+
const idx = normalized.indexOf(marker);
|
|
690155
|
+
if (idx < 0) return null;
|
|
690156
|
+
const rest = normalized.slice(idx + marker.length);
|
|
690157
|
+
const parts = rest.split('/').filter(Boolean);
|
|
690158
|
+
if (parts.length < 2) return null;
|
|
690159
|
+
const group = parts[0];
|
|
690160
|
+
const name = parts[parts.length - 1];
|
|
690161
|
+
const kind = group === 'images' ? 'image'
|
|
690162
|
+
: group === 'videos' ? 'video'
|
|
690163
|
+
: group === 'audio' ? 'audio'
|
|
690164
|
+
: group === 'music' ? 'music'
|
|
690165
|
+
: null;
|
|
690166
|
+
if (!kind || !name) return null;
|
|
690167
|
+
return '/v1/media/file?kind=' + encodeURIComponent(kind) + '&name=' + encodeURIComponent(name);
|
|
690168
|
+
}
|
|
690169
|
+
|
|
690170
|
+
function artifactFromPath(path, hint) {
|
|
690171
|
+
const clean = cleanArtifactPathCandidate(path);
|
|
690172
|
+
if (!clean) return null;
|
|
690173
|
+
const info = fileInfoFor(null, clean);
|
|
690174
|
+
if (info.kind === 'binary' || info.kind === 'archive') return null;
|
|
690175
|
+
const mediaUrl = mediaUrlForStoredPath(clean);
|
|
690176
|
+
return {
|
|
690177
|
+
path: clean,
|
|
690178
|
+
url: mediaUrl || rawFileUrl(clean),
|
|
690179
|
+
name: baseNameForPath(clean),
|
|
690180
|
+
kind: hint || info.kind,
|
|
690181
|
+
mime: info.mime,
|
|
690182
|
+
info,
|
|
690183
|
+
};
|
|
690184
|
+
}
|
|
690185
|
+
|
|
690186
|
+
function artifactFromUrl(url, hint) {
|
|
690187
|
+
const clean = cleanArtifactPathCandidate(url);
|
|
690188
|
+
if (!clean) return null;
|
|
690189
|
+
if (!/^\\/v1\\/media\\/file\\?/.test(clean) && !/^\\/v1\\/files\\/raw\\?/.test(clean) && !/^https?:\\/\\//i.test(clean)) return null;
|
|
690190
|
+
let name = clean;
|
|
690191
|
+
let kind = hint || '';
|
|
690192
|
+
let path = '';
|
|
690193
|
+
try {
|
|
690194
|
+
const u = new URL(clean, window.location.origin);
|
|
690195
|
+
path = u.searchParams.get('path') || '';
|
|
690196
|
+
name = u.searchParams.get('name') || (path ? baseNameForPath(path) : '') || baseNameForPath(u.pathname) || clean;
|
|
690197
|
+
kind = kind || u.searchParams.get('kind') || '';
|
|
690198
|
+
if (kind === 'music') kind = 'audio';
|
|
690199
|
+
} catch {}
|
|
690200
|
+
const info = fileInfoFor({ name, kind }, path || name);
|
|
690201
|
+
return { path, url: clean, name, kind: kind || info.kind, mime: info.mime, info };
|
|
690202
|
+
}
|
|
690203
|
+
|
|
690204
|
+
function uniqueArtifacts(items) {
|
|
690205
|
+
const seen = new Set();
|
|
690206
|
+
const out = [];
|
|
690207
|
+
for (const item of items || []) {
|
|
690208
|
+
if (!item) continue;
|
|
690209
|
+
const key = (item.url || '') + '|' + (item.path || '');
|
|
690210
|
+
if (!key.trim() || seen.has(key)) continue;
|
|
690211
|
+
seen.add(key);
|
|
690212
|
+
out.push(item);
|
|
690213
|
+
}
|
|
690214
|
+
return out;
|
|
690215
|
+
}
|
|
690216
|
+
|
|
690217
|
+
function extractArtifactsFromText(text) {
|
|
690218
|
+
const raw = String(text || '');
|
|
690219
|
+
if (!raw.trim()) return [];
|
|
690220
|
+
const out = [];
|
|
690221
|
+
|
|
690222
|
+
const urlRe = /\\/v1\\/(?:media\\/file|files\\/raw)\\?[^\\s"'<>]+/g;
|
|
690223
|
+
for (const match of raw.matchAll(urlRe)) {
|
|
690224
|
+
out.push(artifactFromUrl(match[0]));
|
|
690225
|
+
}
|
|
690226
|
+
|
|
690227
|
+
const pathRe = /(?:~|\\/|[A-Za-z]:[\\\\/])[^\\s"'<>]+/g;
|
|
690228
|
+
for (const match of raw.matchAll(pathRe)) {
|
|
690229
|
+
const candidate = cleanArtifactPathCandidate(match[0]);
|
|
690230
|
+
if (/^\\/v1\\/(?:media\\/file|files\\/raw)\\?/i.test(candidate)) continue;
|
|
690231
|
+
const info = fileInfoFor(null, candidate);
|
|
690232
|
+
if (isPreviewableArtifactInfo(info)) out.push(artifactFromPath(candidate));
|
|
690233
|
+
}
|
|
690234
|
+
|
|
690235
|
+
const trimmed = raw.trim();
|
|
690236
|
+
if ((trimmed.startsWith('{') && trimmed.endsWith('}')) || (trimmed.startsWith('[') && trimmed.endsWith(']'))) {
|
|
690237
|
+
try {
|
|
690238
|
+
out.push(...extractArtifactsFromValue(JSON.parse(trimmed)));
|
|
690239
|
+
} catch {}
|
|
690240
|
+
}
|
|
690241
|
+
|
|
690242
|
+
return uniqueArtifacts(out);
|
|
690243
|
+
}
|
|
690244
|
+
|
|
690245
|
+
function extractArtifactsFromValue(value) {
|
|
690246
|
+
const out = [];
|
|
690247
|
+
const walk = (v, key) => {
|
|
690248
|
+
if (v == null) return;
|
|
690249
|
+
if (typeof v === 'string') {
|
|
690250
|
+
const lowerKey = String(key || '').toLowerCase();
|
|
690251
|
+
if (/^(path|file|filename|output|url|href|src|artifact|download)$/.test(lowerKey)) {
|
|
690252
|
+
out.push(artifactFromUrl(v) || artifactFromPath(v));
|
|
690253
|
+
}
|
|
690254
|
+
out.push(...extractArtifactsFromText(v));
|
|
690255
|
+
return;
|
|
690256
|
+
}
|
|
690257
|
+
if (Array.isArray(v)) {
|
|
690258
|
+
for (const item of v.slice(0, 20)) walk(item, key);
|
|
690259
|
+
return;
|
|
690260
|
+
}
|
|
690261
|
+
if (typeof v === 'object') {
|
|
690262
|
+
const obj = v;
|
|
690263
|
+
const kind = typeof obj.kind === 'string' ? obj.kind : '';
|
|
690264
|
+
const direct = obj.url || obj.href || obj.src || obj.path || obj.output || obj.file || obj.filename;
|
|
690265
|
+
if (typeof direct === 'string') out.push(artifactFromUrl(direct, kind) || artifactFromPath(direct, kind));
|
|
690266
|
+
for (const [k, child] of Object.entries(obj).slice(0, 30)) walk(child, k);
|
|
690267
|
+
}
|
|
690268
|
+
};
|
|
690269
|
+
walk(value, '');
|
|
690270
|
+
return uniqueArtifacts(out);
|
|
690271
|
+
}
|
|
690272
|
+
|
|
690273
|
+
async function downloadArtifact(artifact) {
|
|
690274
|
+
const url = artifact.url || (artifact.path ? rawFileUrl(artifact.path) : '');
|
|
690275
|
+
if (!url) return;
|
|
690276
|
+
try {
|
|
690277
|
+
const r = await fetch(url, { headers: headers() });
|
|
690278
|
+
if (!r.ok) throw new Error('HTTP ' + r.status);
|
|
690279
|
+
const blob = await r.blob();
|
|
690280
|
+
const href = URL.createObjectURL(blob);
|
|
690281
|
+
const a = document.createElement('a');
|
|
690282
|
+
a.href = href;
|
|
690283
|
+
a.download = artifact.name || baseNameForPath(artifact.path || url) || 'artifact';
|
|
690284
|
+
document.body.appendChild(a);
|
|
690285
|
+
a.click();
|
|
690286
|
+
a.remove();
|
|
690287
|
+
setTimeout(() => URL.revokeObjectURL(href), 5000);
|
|
690288
|
+
} catch (e) {
|
|
690289
|
+
const s = document.getElementById('status');
|
|
690290
|
+
if (s) {
|
|
690291
|
+
const old = s.textContent;
|
|
690292
|
+
s.textContent = 'download failed: ' + (e && e.message ? e.message : String(e));
|
|
690293
|
+
setTimeout(() => { s.textContent = old; }, 2500);
|
|
690294
|
+
}
|
|
690295
|
+
}
|
|
690296
|
+
}
|
|
690297
|
+
|
|
690298
|
+
function previewArtifact(artifact) {
|
|
690299
|
+
if (artifact.path) {
|
|
690300
|
+
previewFile(artifact.path);
|
|
690301
|
+
return;
|
|
690302
|
+
}
|
|
690303
|
+
const info = artifact.info || fileInfoFor({ name: artifact.name, kind: artifact.kind }, artifact.name || artifact.url);
|
|
690304
|
+
const shell = createFilePreviewShell(artifact.name || artifact.url, info);
|
|
690305
|
+
const src = artifact.url;
|
|
690306
|
+
const openLink = shell.card.querySelector('a');
|
|
690307
|
+
if (openLink) openLink.href = src;
|
|
690308
|
+
if (info.kind === 'audio') {
|
|
690309
|
+
const audio = document.createElement('audio');
|
|
690310
|
+
audio.controls = true;
|
|
690311
|
+
audio.preload = 'metadata';
|
|
690312
|
+
audio.src = src;
|
|
690313
|
+
audio.style.cssText = 'width:min(680px,82vw);display:block';
|
|
690314
|
+
shell.body.appendChild(audio);
|
|
690315
|
+
} else if (info.kind === 'video') {
|
|
690316
|
+
const video = document.createElement('video');
|
|
690317
|
+
video.controls = true;
|
|
690318
|
+
video.preload = 'metadata';
|
|
690319
|
+
video.src = src;
|
|
690320
|
+
video.style.cssText = 'max-width:86vw;max-height:76vh;background:#000;display:block';
|
|
690321
|
+
shell.body.appendChild(video);
|
|
690322
|
+
} else if (info.kind === 'image') {
|
|
690323
|
+
const img = document.createElement('img');
|
|
690324
|
+
img.src = src;
|
|
690325
|
+
img.alt = artifact.name || 'artifact';
|
|
690326
|
+
img.style.cssText = 'max-width:86vw;max-height:76vh;object-fit:contain;display:block';
|
|
690327
|
+
shell.body.appendChild(img);
|
|
690328
|
+
} else {
|
|
690329
|
+
const link = document.createElement('a');
|
|
690330
|
+
link.href = src;
|
|
690331
|
+
link.target = '_blank';
|
|
690332
|
+
link.rel = 'noopener noreferrer';
|
|
690333
|
+
link.textContent = 'open artifact';
|
|
690334
|
+
link.style.cssText = 'color:var(--color-brand);border:1px solid var(--color-border);border-radius:3px;padding:6px 10px;text-decoration:none';
|
|
690335
|
+
shell.body.appendChild(link);
|
|
690336
|
+
}
|
|
690337
|
+
document.body.appendChild(shell.modal);
|
|
690338
|
+
}
|
|
690339
|
+
|
|
690340
|
+
function appendArtifactControls(parent, artifacts) {
|
|
690341
|
+
const items = uniqueArtifacts(artifacts);
|
|
690342
|
+
if (!parent || items.length === 0) return null;
|
|
690343
|
+
const wrap = document.createElement('div');
|
|
690344
|
+
wrap.className = 'artifact-controls';
|
|
690345
|
+
wrap.style.cssText = 'display:flex;flex-direction:column;gap:6px;margin:6px 0 2px 0';
|
|
690346
|
+
for (const artifact of items) {
|
|
690347
|
+
const info = artifact.info || fileInfoFor({ name: artifact.name, kind: artifact.kind }, artifact.path || artifact.name || artifact.url);
|
|
690348
|
+
const row = document.createElement('div');
|
|
690349
|
+
row.style.cssText = 'display:flex;align-items:center;gap:8px;min-width:0;background:var(--color-bg);border:1px solid var(--color-border);border-left:2px solid var(--color-brand);border-radius:4px;padding:6px 8px;color:var(--color-fg);font-size:0.68rem';
|
|
690350
|
+
const label = document.createElement('span');
|
|
690351
|
+
label.textContent = (info.icon || '◇') + ' ' + (artifact.name || baseNameForPath(artifact.path || artifact.url || 'artifact'));
|
|
690352
|
+
label.title = artifact.path || artifact.url || '';
|
|
690353
|
+
label.style.cssText = 'min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;flex:1';
|
|
690354
|
+
row.appendChild(label);
|
|
690355
|
+
|
|
690356
|
+
if (info.kind === 'audio') {
|
|
690357
|
+
const audio = document.createElement('audio');
|
|
690358
|
+
audio.controls = true;
|
|
690359
|
+
audio.preload = 'metadata';
|
|
690360
|
+
audio.src = artifact.url || rawFileUrl(artifact.path);
|
|
690361
|
+
audio.style.cssText = 'width:min(320px,40vw);height:28px;flex:0 1 320px';
|
|
690362
|
+
row.appendChild(audio);
|
|
690363
|
+
} else if (isPreviewableArtifactInfo(info)) {
|
|
690364
|
+
const view = document.createElement('button');
|
|
690365
|
+
view.type = 'button';
|
|
690366
|
+
view.textContent = 'view';
|
|
690367
|
+
view.title = 'View ' + info.label;
|
|
690368
|
+
view.style.cssText = 'background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-brand);border-radius:3px;padding:3px 8px;cursor:pointer;font:inherit;font-size:0.64rem;flex-shrink:0';
|
|
690369
|
+
view.onclick = (e) => { e.stopPropagation(); previewArtifact(artifact); };
|
|
690370
|
+
row.appendChild(view);
|
|
690371
|
+
}
|
|
690372
|
+
|
|
690373
|
+
const download = document.createElement('button');
|
|
690374
|
+
download.type = 'button';
|
|
690375
|
+
download.textContent = 'download';
|
|
690376
|
+
download.title = 'Download ' + (artifact.name || 'artifact');
|
|
690377
|
+
download.style.cssText = 'background:var(--color-bg-input);border:1px solid var(--color-border);color:var(--color-brand);border-radius:3px;padding:3px 8px;cursor:pointer;font:inherit;font-size:0.64rem;flex-shrink:0';
|
|
690378
|
+
download.onclick = (e) => { e.stopPropagation(); downloadArtifact(artifact); };
|
|
690379
|
+
row.appendChild(download);
|
|
690380
|
+
wrap.appendChild(row);
|
|
690381
|
+
}
|
|
690382
|
+
parent.appendChild(wrap);
|
|
690383
|
+
return wrap;
|
|
690384
|
+
}
|
|
690385
|
+
|
|
690386
|
+
function appendArtifactsForText(parent, text) {
|
|
690387
|
+
return appendArtifactControls(parent, extractArtifactsFromText(text));
|
|
690388
|
+
}
|
|
690389
|
+
|
|
689671
690390
|
function appendFileKindBadge(row, info) {
|
|
689672
690391
|
if (!info || info.kind === 'text') return;
|
|
689673
690392
|
const badge = document.createElement('span');
|
|
@@ -690446,7 +691165,9 @@ async function restoreChatSession() {
|
|
|
690446
691165
|
messages: messages,
|
|
690447
691166
|
model: data.model || modelSelect.value,
|
|
690448
691167
|
updatedAt: data.updated_at || data.updatedAt || new Date().toISOString(),
|
|
690449
|
-
|
|
691168
|
+
title: data.title || (($chatSessions.get && $chatSessions.get()) || {})[data.id]?.title || sessionDisplayTitle(data.id, { messages }),
|
|
691169
|
+
name: data.title || (($chatSessions.get && $chatSessions.get()) || {})[data.id]?.name || sessionDisplayTitle(data.id, { messages }),
|
|
691170
|
+
preview: data.preview || messages.slice(-1)[0]?.content?.slice(0, 50) || 'empty',
|
|
690450
691171
|
};
|
|
690451
691172
|
saveScopedSessions(saved);
|
|
690452
691173
|
$chatSessions.set({ ...(($chatSessions.get && $chatSessions.get()) || {}), ...saved });
|
|
@@ -691633,7 +692354,7 @@ function _renderSidebarChats(filter) {
|
|
|
691633
692354
|
|
|
691634
692355
|
const renderRow = (id) => {
|
|
691635
692356
|
const s = sessions[id] || {};
|
|
691636
|
-
const title = (
|
|
692357
|
+
const title = sessionDisplayTitle(id, s).toString();
|
|
691637
692358
|
const cls = 'sb-chat' + (id === activeId ? ' active' : '');
|
|
691638
692359
|
const safeId = String(id).replace(/'/g, "\\\\'");
|
|
691639
692360
|
const safeTitle = title.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
|
|
@@ -691823,32 +692544,21 @@ async function loadSettingsConnections() {
|
|
|
691823
692544
|
'</div>';
|
|
691824
692545
|
// Stash history globally so click handlers can resolve index → record.
|
|
691825
692546
|
window.__omniusEndpointHistory = history;
|
|
692547
|
+
const activeProviderId = settingsProviderIdForUrl(ep);
|
|
692548
|
+
const selectedProviderId = settingsProviderById(window.__omniusSelectedProviderModule)
|
|
692549
|
+
? window.__omniusSelectedProviderModule
|
|
692550
|
+
: (activeProviderId || 'ollama');
|
|
692551
|
+
window.__omniusSelectedProviderModule = selectedProviderId;
|
|
691826
692552
|
host.innerHTML =
|
|
691827
692553
|
'<div style="display:flex;flex-direction:column;gap:14px">' +
|
|
691828
|
-
// Quick presets — one-click apply for the common defaults so the
|
|
691829
|
-
// user doesn't have to type or even pick a backend type. Selecting
|
|
691830
|
-
// a preset fills the URL + backend type fields below; clicking
|
|
691831
|
-
// "Apply preset" saves directly without further input.
|
|
691832
692554
|
'<div>' +
|
|
691833
|
-
'<
|
|
691834
|
-
|
|
691835
|
-
'<
|
|
691836
|
-
'<option value="">— select preset —</option>' +
|
|
691837
|
-
'<option value="ollama">Ollama (http://127.0.0.1:11434)</option>' +
|
|
691838
|
-
'<option value="ollama-lan">Ollama on LAN (http://0.0.0.0:11434)</option>' +
|
|
691839
|
-
'<option value="vllm">vLLM (http://127.0.0.1:8000/v1)</option>' +
|
|
691840
|
-
'<option value="lmstudio">LM Studio (http://127.0.0.1:1234/v1)</option>' +
|
|
691841
|
-
'<option value="openai">OpenAI (https://api.openai.com/v1)</option>' +
|
|
691842
|
-
'<option value="anthropic">Anthropic (https://api.anthropic.com/v1)</option>' +
|
|
691843
|
-
'<option value="chutes">Chutes (https://llm.chutes.ai/v1)</option>' +
|
|
691844
|
-
'<option value="groq">Groq (https://api.groq.com/openai/v1)</option>' +
|
|
691845
|
-
'<option value="deepinfra">DeepInfra (https://api.deepinfra.com/v1/openai)</option>' +
|
|
691846
|
-
'</select>' +
|
|
691847
|
-
'<button class="omnius-btn-secondary" type="button" onclick="applyEndpointPreset(true)" style="background:var(--color-accent);color:var(--color-accent-fg);border-color:var(--color-accent)">apply preset</button>' +
|
|
691848
|
-
'<button class="omnius-btn-secondary" type="button" onclick="applyEndpointPreset(false)" title="fill the fields below without saving">load to form</button>' +
|
|
692555
|
+
'<div style="display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:8px">' +
|
|
692556
|
+
'<label style="display:block;font-size:0.78rem;font-weight:500">Provider modules</label>' +
|
|
692557
|
+
'<span style="font-size:0.68rem;color:var(--color-fg-muted)">' + escapeHtml(settingsProviderGroupSummary()) + '</span>' +
|
|
691849
692558
|
'</div>' +
|
|
691850
|
-
|
|
692559
|
+
renderSettingsProviderModules(selectedProviderId, ep) +
|
|
691851
692560
|
'</div>' +
|
|
692561
|
+
'<div id="settings-provider-setup" class="settings-provider-setup">' + renderSettingsProviderSetup(selectedProviderId) + '</div>' +
|
|
691852
692562
|
'<div>' +
|
|
691853
692563
|
'<label style="display:block;font-size:0.78rem;font-weight:500;margin-bottom:6px">Endpoint history</label>' +
|
|
691854
692564
|
histHTML +
|
|
@@ -691889,17 +692599,142 @@ async function loadSettingsConnections() {
|
|
|
691889
692599
|
// Map preset key → { url, backendType, requiresAuth, label }. Used by
|
|
691890
692600
|
// applyEndpointPreset() below to populate the URL + type fields with one
|
|
691891
692601
|
// click, optionally saving immediately.
|
|
691892
|
-
const
|
|
691893
|
-
'ollama':
|
|
691894
|
-
'
|
|
691895
|
-
'vllm':
|
|
691896
|
-
'
|
|
691897
|
-
'
|
|
691898
|
-
'
|
|
691899
|
-
'chutes':
|
|
691900
|
-
'groq':
|
|
691901
|
-
'deepinfra':
|
|
691902
|
-
}
|
|
692602
|
+
const _OMNIUS_ENDPOINT_PROVIDERS = [
|
|
692603
|
+
{ id: 'ollama', label: 'Ollama', group: 'Local models', domain: 'ollama.com', url: 'http://127.0.0.1:11434', backendType: 'ollama', local: true, description: 'Local Ollama runtime on port 11434.', docsUrl: 'https://docs.ollama.com/api' },
|
|
692604
|
+
{ id: 'lmstudio', label: 'LM Studio', group: 'Local models', domain: 'lmstudio.ai', url: 'http://127.0.0.1:1234/v1', backendType: 'vllm', local: true, description: 'Local OpenAI-compatible server on port 1234.', docsUrl: 'https://lmstudio.ai/docs' },
|
|
692605
|
+
{ id: 'vllm', label: 'vLLM', group: 'Local models', domain: 'docs.vllm.ai', url: 'http://127.0.0.1:8000/v1', backendType: 'vllm', local: true, description: 'Self-hosted OpenAI-compatible vLLM endpoint.', docsUrl: 'https://docs.vllm.ai' },
|
|
692606
|
+
{ id: 'openai', label: 'OpenAI', group: 'Cloud providers', domain: 'openai.com', url: 'https://api.openai.com/v1', backendType: 'vllm', requiresAuth: true, description: 'OpenAI API-compatible models.', apiKeyUrl: 'https://platform.openai.com/api-keys', docsUrl: 'https://platform.openai.com/docs/api-reference/authentication' },
|
|
692607
|
+
{ id: 'anthropic', label: 'Anthropic', group: 'Cloud providers', domain: 'anthropic.com', url: 'https://api.anthropic.com/v1', backendType: 'vllm', requiresAuth: true, description: 'Claude via Anthropic API.', apiKeyUrl: 'https://console.anthropic.com/settings/keys', docsUrl: 'https://docs.anthropic.com/en/api/overview' },
|
|
692608
|
+
{ id: 'openrouter', label: 'OpenRouter', group: 'Cloud providers', domain: 'openrouter.ai', url: 'https://openrouter.ai/api/v1', backendType: 'vllm', requiresAuth: true, description: 'OpenAI-compatible routing across many hosted models.', apiKeyUrl: 'https://openrouter.ai/keys', docsUrl: 'https://openrouter.ai/docs' },
|
|
692609
|
+
{ id: 'chutes', label: 'Chutes', group: 'Cloud providers', domain: 'chutes.ai', url: 'https://llm.chutes.ai/v1', backendType: 'vllm', requiresAuth: true, description: 'Chutes OpenAI-compatible model endpoint.', apiKeyUrl: 'https://chutes.ai/app/api', docsUrl: 'https://docs.chutes.ai' },
|
|
692610
|
+
{ id: 'groq', label: 'Groq', group: 'Cloud providers', domain: 'groq.com', url: 'https://api.groq.com/openai/v1', backendType: 'vllm', requiresAuth: true, description: 'Groq OpenAI-compatible inference.', apiKeyUrl: 'https://console.groq.com/keys', docsUrl: 'https://console.groq.com/docs' },
|
|
692611
|
+
{ id: 'deepinfra', label: 'DeepInfra', group: 'Cloud providers', domain: 'deepinfra.com', url: 'https://api.deepinfra.com/v1/openai', backendType: 'vllm', requiresAuth: true, description: 'DeepInfra OpenAI-compatible hosted models.', apiKeyUrl: 'https://deepinfra.com/dash/api_keys', docsUrl: 'https://deepinfra.com/docs/openai_api' },
|
|
692612
|
+
{ id: 'together', label: 'Together AI', group: 'Cloud providers', domain: 'together.ai', url: 'https://api.together.xyz/v1', backendType: 'vllm', requiresAuth: true, description: 'Together OpenAI-compatible inference.', apiKeyUrl: 'https://api.together.xyz/settings/api-keys', docsUrl: 'https://docs.together.ai/docs/openai-api-compatibility' },
|
|
692613
|
+
{ id: 'fireworks', label: 'Fireworks', group: 'Cloud providers', domain: 'fireworks.ai', url: 'https://api.fireworks.ai/inference/v1', backendType: 'vllm', requiresAuth: true, description: 'Fireworks OpenAI-compatible inference.', apiKeyUrl: 'https://fireworks.ai/account/api-keys', docsUrl: 'https://docs.fireworks.ai' },
|
|
692614
|
+
{ id: 'mistral', label: 'Mistral', group: 'Cloud providers', domain: 'mistral.ai', url: 'https://api.mistral.ai/v1', backendType: 'vllm', requiresAuth: true, description: 'Mistral hosted model endpoint.', apiKeyUrl: 'https://console.mistral.ai/api-keys', docsUrl: 'https://docs.mistral.ai' },
|
|
692615
|
+
{ id: 'cerebras', label: 'Cerebras', group: 'Cloud providers', domain: 'cerebras.ai', url: 'https://api.cerebras.ai/v1', backendType: 'vllm', requiresAuth: true, description: 'Cerebras OpenAI-compatible inference.', apiKeyUrl: 'https://cloud.cerebras.ai/platform', docsUrl: 'https://inference-docs.cerebras.ai' },
|
|
692616
|
+
{ id: 'sambanova', label: 'SambaNova', group: 'Cloud providers', domain: 'sambanova.ai', url: 'https://api.sambanova.ai/v1', backendType: 'vllm', requiresAuth: true, description: 'SambaNova OpenAI-compatible inference.', apiKeyUrl: 'https://cloud.sambanova.ai/apis', docsUrl: 'https://docs.sambanova.ai' },
|
|
692617
|
+
{ id: 'nvidia', label: 'NVIDIA NIM', group: 'Cloud providers', domain: 'nvidia.com', url: 'https://integrate.api.nvidia.com/v1', backendType: 'vllm', requiresAuth: true, description: 'NVIDIA-hosted NIM models.', apiKeyUrl: 'https://build.nvidia.com', docsUrl: 'https://docs.api.nvidia.com/nim' },
|
|
692618
|
+
{ id: 'hyperbolic', label: 'Hyperbolic', group: 'Cloud providers', domain: 'hyperbolic.xyz', url: 'https://api.hyperbolic.xyz/v1', backendType: 'vllm', requiresAuth: true, description: 'Hyperbolic OpenAI-compatible inference.', apiKeyUrl: 'https://app.hyperbolic.xyz/settings', docsUrl: 'https://docs.hyperbolic.xyz' },
|
|
692619
|
+
{ id: 'custom', label: 'Custom', group: 'Custom endpoint', domain: '', url: '', backendType: 'vllm', requiresAuth: false, description: 'Any OpenAI-compatible endpoint.' },
|
|
692620
|
+
];
|
|
692621
|
+
const _OMNIUS_ENDPOINT_PRESETS = Object.fromEntries(_OMNIUS_ENDPOINT_PROVIDERS.map(p => [p.id, p]));
|
|
692622
|
+
|
|
692623
|
+
function settingsProviderById(id) {
|
|
692624
|
+
return _OMNIUS_ENDPOINT_PROVIDERS.find(p => p.id === id) || null;
|
|
692625
|
+
}
|
|
692626
|
+
|
|
692627
|
+
function settingsProviderIdForUrl(url) {
|
|
692628
|
+
const u = String(url || '').toLowerCase();
|
|
692629
|
+
if (!u) return '';
|
|
692630
|
+
if (u.includes('11434') || u.includes('ollama')) return 'ollama';
|
|
692631
|
+
if (u.includes('1234') || u.includes('lmstudio')) return 'lmstudio';
|
|
692632
|
+
if (u.includes('8000') || u.includes('vllm')) return 'vllm';
|
|
692633
|
+
if (u.includes('api.openai.com')) return 'openai';
|
|
692634
|
+
if (u.includes('api.anthropic.com')) return 'anthropic';
|
|
692635
|
+
if (u.includes('openrouter.ai')) return 'openrouter';
|
|
692636
|
+
if (u.includes('chutes.ai')) return 'chutes';
|
|
692637
|
+
if (u.includes('api.groq.com')) return 'groq';
|
|
692638
|
+
if (u.includes('api.deepinfra.com')) return 'deepinfra';
|
|
692639
|
+
if (u.includes('api.together.xyz')) return 'together';
|
|
692640
|
+
if (u.includes('api.fireworks.ai')) return 'fireworks';
|
|
692641
|
+
if (u.includes('api.mistral.ai')) return 'mistral';
|
|
692642
|
+
if (u.includes('api.cerebras.ai')) return 'cerebras';
|
|
692643
|
+
if (u.includes('api.sambanova.ai')) return 'sambanova';
|
|
692644
|
+
if (u.includes('integrate.api.nvidia.com')) return 'nvidia';
|
|
692645
|
+
if (u.includes('api.hyperbolic.xyz')) return 'hyperbolic';
|
|
692646
|
+
return 'custom';
|
|
692647
|
+
}
|
|
692648
|
+
|
|
692649
|
+
function settingsProviderGroupSummary() {
|
|
692650
|
+
const groups = [];
|
|
692651
|
+
for (const p of _OMNIUS_ENDPOINT_PROVIDERS) {
|
|
692652
|
+
if (!groups.includes(p.group)) groups.push(p.group);
|
|
692653
|
+
}
|
|
692654
|
+
return groups.join(' / ');
|
|
692655
|
+
}
|
|
692656
|
+
|
|
692657
|
+
function settingsProviderIcon(provider) {
|
|
692658
|
+
const initial = escapeHtml(String(provider.label || '?').trim().charAt(0).toUpperCase() || '?');
|
|
692659
|
+
if (!provider.domain) return '<span class="settings-provider-brand"><span>' + initial + '</span></span>';
|
|
692660
|
+
const src = 'https://www.google.com/s2/favicons?domain=' + encodeURIComponent(provider.domain) + '&sz=64';
|
|
692661
|
+
return '<span class="settings-provider-brand"><img src="' + escapeHtml(src) + '" alt="" onerror="this.hidden=true;this.nextElementSibling.hidden=false"><span hidden>' + initial + '</span></span>';
|
|
692662
|
+
}
|
|
692663
|
+
|
|
692664
|
+
function renderSettingsProviderModules(selectedId, currentUrl) {
|
|
692665
|
+
const activeId = settingsProviderIdForUrl(currentUrl);
|
|
692666
|
+
return '<div class="settings-provider-module-grid">' + _OMNIUS_ENDPOINT_PROVIDERS.map(provider => {
|
|
692667
|
+
const selected = provider.id === selectedId;
|
|
692668
|
+
const active = provider.id === activeId;
|
|
692669
|
+
const cls = 'settings-provider-module' + (selected ? ' active' : '');
|
|
692670
|
+
const safeId = escapeHtml(provider.id);
|
|
692671
|
+
const meta = provider.group + (active ? ' - active' : (provider.requiresAuth ? ' - API key' : ''));
|
|
692672
|
+
return '<button type="button" class="' + cls + '" data-provider-id="' + safeId + '" onclick="selectSettingsProviderModule(\\'' + safeId + '\\', false)">' +
|
|
692673
|
+
settingsProviderIcon(provider) +
|
|
692674
|
+
'<strong>' + escapeHtml(provider.label) + '</strong>' +
|
|
692675
|
+
'<small>' + escapeHtml(meta) + '</small>' +
|
|
692676
|
+
'</button>';
|
|
692677
|
+
}).join('') + '</div>';
|
|
692678
|
+
}
|
|
692679
|
+
|
|
692680
|
+
function renderSettingsProviderSetup(providerId) {
|
|
692681
|
+
const provider = settingsProviderById(providerId) || settingsProviderById('custom');
|
|
692682
|
+
if (!provider) return '';
|
|
692683
|
+
const endpoint = provider.url || 'custom URL';
|
|
692684
|
+
const auth = provider.requiresAuth ? 'API key required' : (provider.local ? 'Local endpoint' : 'Auth optional');
|
|
692685
|
+
const links = [
|
|
692686
|
+
provider.apiKeyUrl ? '<a class="settings-provider-link" href="' + escapeHtml(provider.apiKeyUrl) + '" target="_blank" rel="noopener noreferrer">key</a>' : '',
|
|
692687
|
+
provider.docsUrl ? '<a class="settings-provider-link" href="' + escapeHtml(provider.docsUrl) + '" target="_blank" rel="noopener noreferrer">docs</a>' : '',
|
|
692688
|
+
].filter(Boolean).join('');
|
|
692689
|
+
return '<div class="settings-provider-setup-head">' +
|
|
692690
|
+
settingsProviderIcon(provider) +
|
|
692691
|
+
'<div><strong>' + escapeHtml(provider.label) + '</strong><small>' + escapeHtml(provider.description || provider.group) + '</small></div>' +
|
|
692692
|
+
'</div>' +
|
|
692693
|
+
'<div class="settings-provider-meta">Endpoint <code>' + escapeHtml(endpoint) + '</code> · ' + escapeHtml(auth) + '</div>' +
|
|
692694
|
+
'<div class="settings-provider-actions">' +
|
|
692695
|
+
'<button class="omnius-btn-secondary" type="button" onclick="selectSettingsProviderModule(\\'' + escapeHtml(provider.id) + '\\', true)" style="background:var(--color-accent);color:var(--color-accent-fg);border-color:var(--color-accent)">use provider</button>' +
|
|
692696
|
+
'<button class="omnius-btn-secondary" type="button" onclick="selectSettingsProviderModule(\\'' + escapeHtml(provider.id) + '\\', false)">load to form</button>' +
|
|
692697
|
+
'<button class="omnius-btn-secondary" type="button" onclick="testSettingsConnections()">test</button>' +
|
|
692698
|
+
links +
|
|
692699
|
+
'</div>';
|
|
692700
|
+
}
|
|
692701
|
+
|
|
692702
|
+
function updateSettingsProviderSetup(providerId) {
|
|
692703
|
+
const host = document.getElementById('settings-provider-setup');
|
|
692704
|
+
if (host) host.innerHTML = renderSettingsProviderSetup(providerId);
|
|
692705
|
+
document.querySelectorAll('.settings-provider-module').forEach(btn => {
|
|
692706
|
+
btn.classList.toggle('active', btn.getAttribute('data-provider-id') === providerId);
|
|
692707
|
+
});
|
|
692708
|
+
}
|
|
692709
|
+
|
|
692710
|
+
async function selectSettingsProviderModule(providerId, apply) {
|
|
692711
|
+
const provider = settingsProviderById(providerId);
|
|
692712
|
+
if (!provider) return;
|
|
692713
|
+
window.__omniusSelectedProviderModule = provider.id;
|
|
692714
|
+
updateSettingsProviderSetup(provider.id);
|
|
692715
|
+
const inp = document.getElementById('settings-conn-endpoint');
|
|
692716
|
+
const bt = document.getElementById('settings-conn-backend-type');
|
|
692717
|
+
const auth = document.getElementById('settings-conn-auth');
|
|
692718
|
+
const status = document.getElementById('settings-conn-status');
|
|
692719
|
+
if (inp && provider.url) inp.value = provider.url;
|
|
692720
|
+
if (bt && provider.backendType) bt.value = provider.backendType;
|
|
692721
|
+
if (status) {
|
|
692722
|
+
status.textContent = provider.url ? (provider.label + ' loaded') : 'enter a custom endpoint URL below';
|
|
692723
|
+
status.style.color = 'var(--color-fg-muted)';
|
|
692724
|
+
}
|
|
692725
|
+
if (!apply) return;
|
|
692726
|
+
if (!provider.url && inp && !String(inp.value || '').trim()) {
|
|
692727
|
+
if (status) { status.textContent = 'enter a custom endpoint URL first'; status.style.color = 'var(--color-warning)'; }
|
|
692728
|
+
return;
|
|
692729
|
+
}
|
|
692730
|
+
if (provider.requiresAuth && (!auth || !auth.value) && !window.__omniusAuthAlreadySet) {
|
|
692731
|
+
if (status) { status.textContent = provider.label + ' requires an auth key'; status.style.color = 'var(--color-warning)'; }
|
|
692732
|
+
return;
|
|
692733
|
+
}
|
|
692734
|
+
await saveSettingsConnections();
|
|
692735
|
+
}
|
|
692736
|
+
window.selectSettingsProviderModule = selectSettingsProviderModule;
|
|
692737
|
+
window.updateSettingsProviderSetup = updateSettingsProviderSetup;
|
|
691903
692738
|
|
|
691904
692739
|
// One-click endpoint switcher. apply=true saves directly (no typing
|
|
691905
692740
|
// needed). apply=false just fills the URL/backend-type fields so the
|
|
@@ -692020,7 +692855,7 @@ function autoDetectBackendType(url) {
|
|
|
692020
692855
|
let detected = 'unknown';
|
|
692021
692856
|
if (u.includes('11434') || u.includes('ollama')) detected = 'ollama';
|
|
692022
692857
|
else if (u.startsWith('peer://')) detected = 'nexus';
|
|
692023
|
-
else if (u.includes('vllm') || u.includes('openai.com') || u.includes('api.anthropic.com') || u.includes('chutes') || u.includes('groq') || u.includes('deepinfra') || u.includes('/v1')) detected = 'vllm';
|
|
692858
|
+
else if (u.includes('vllm') || u.includes('lmstudio') || u.includes('openai.com') || u.includes('api.anthropic.com') || u.includes('openrouter') || u.includes('chutes') || u.includes('groq') || u.includes('deepinfra') || u.includes('together') || u.includes('fireworks') || u.includes('mistral') || u.includes('cerebras') || u.includes('sambanova') || u.includes('nvidia') || u.includes('hyperbolic') || u.includes('/v1')) detected = 'vllm';
|
|
692024
692859
|
if (sel.value === '' || sel.value === 'unknown') sel.value = detected;
|
|
692025
692860
|
}
|
|
692026
692861
|
|
|
@@ -701804,6 +702639,10 @@ ${historyLines}
|
|
|
701804
702639
|
jsonResponse(res, 200, {
|
|
701805
702640
|
id: session.id,
|
|
701806
702641
|
model: session.model,
|
|
702642
|
+
title: session.title ?? null,
|
|
702643
|
+
preview: session.preview ?? null,
|
|
702644
|
+
source: session.source ?? "web",
|
|
702645
|
+
projectRoot: session.projectRoot ?? null,
|
|
701807
702646
|
messages: publicMessages,
|
|
701808
702647
|
message_count: publicMessages.length,
|
|
701809
702648
|
tokens_in: session.tokensIn,
|
|
@@ -707183,15 +708022,21 @@ ${entry.fullContent}`
|
|
|
707183
708022
|
);
|
|
707184
708023
|
};
|
|
707185
708024
|
let liveShellBlock = null;
|
|
708025
|
+
const liveShellFingerprint = () => liveShellBlock ? shellLiveBlockFingerprint(liveShellBlock.state) : "";
|
|
708026
|
+
let lastLiveShellPaint = "";
|
|
707186
708027
|
const scheduleLiveShellRepaint = () => {
|
|
707187
708028
|
if (!liveShellBlock || liveShellBlock.repaintTimer || !statusBar?.isActive)
|
|
707188
708029
|
return;
|
|
707189
708030
|
liveShellBlock.repaintTimer = setTimeout(() => {
|
|
707190
708031
|
if (!liveShellBlock) return;
|
|
707191
708032
|
liveShellBlock.repaintTimer = null;
|
|
707192
|
-
|
|
708033
|
+
const fp = liveShellFingerprint();
|
|
708034
|
+
if (fp !== lastLiveShellPaint) {
|
|
708035
|
+
lastLiveShellPaint = fp;
|
|
708036
|
+
if (statusBar?.isActive) statusBar.refreshDynamicBlocks();
|
|
708037
|
+
}
|
|
707193
708038
|
if (liveShellBlock.state.status === "running") scheduleLiveShellRepaint();
|
|
707194
|
-
},
|
|
708039
|
+
}, 120);
|
|
707195
708040
|
liveShellBlock.repaintTimer.unref?.();
|
|
707196
708041
|
};
|
|
707197
708042
|
let gpuRecoveryBlock = null;
|
|
@@ -707349,6 +708194,7 @@ ${entry.fullContent}`
|
|
|
707349
708194
|
const state = createShellLiveBlockState(command);
|
|
707350
708195
|
const id = `shell-live-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
707351
708196
|
liveShellBlock = { id, state, repaintTimer: null };
|
|
708197
|
+
lastLiveShellPaint = "";
|
|
707352
708198
|
liveShellStatusBar.registerDynamicBlock(
|
|
707353
708199
|
id,
|
|
707354
708200
|
(width) => buildShellLiveBlockLines(state, width)
|
|
@@ -713903,6 +714749,13 @@ Rationale: ${proposal.rationale}${provenanceNote}`;
|
|
|
713903
714749
|
process.stderr.write(c3.red("Clipboard paste failed\n"));
|
|
713904
714750
|
}
|
|
713905
714751
|
});
|
|
714752
|
+
rl.on("ctrl-u", () => {
|
|
714753
|
+
try {
|
|
714754
|
+
toggleAll();
|
|
714755
|
+
statusBar?.refreshDynamicBlocks();
|
|
714756
|
+
} catch {
|
|
714757
|
+
}
|
|
714758
|
+
});
|
|
713906
714759
|
rl.on("close", () => {
|
|
713907
714760
|
if (interactiveExiting) return;
|
|
713908
714761
|
interactiveExiting = true;
|
|
@@ -714495,6 +715348,7 @@ var init_interactive = __esm({
|
|
|
714495
715348
|
init_platforms();
|
|
714496
715349
|
init_status_bar();
|
|
714497
715350
|
init_shell_live_block();
|
|
715351
|
+
init_tool_collapse_store();
|
|
714498
715352
|
init_daemon_registry();
|
|
714499
715353
|
init_dist9();
|
|
714500
715354
|
init_overlay_lock();
|