omnius 1.0.487 → 1.0.489
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 +596 -162
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -616964,6 +616964,147 @@ reason=${decision2.reason} confidence=${decision2.confidence.toFixed(2)} source=
|
|
|
616964
616964
|
}
|
|
616965
616965
|
});
|
|
616966
616966
|
|
|
616967
|
+
// packages/cli/src/tui/conversation-context.ts
|
|
616968
|
+
import { statfsSync as statfsSync7 } from "node:fs";
|
|
616969
|
+
function buildConversationRuntimeContext(now2 = /* @__PURE__ */ new Date(), repoRoot) {
|
|
616970
|
+
const date = new Intl.DateTimeFormat("en-US", {
|
|
616971
|
+
weekday: "long",
|
|
616972
|
+
year: "numeric",
|
|
616973
|
+
month: "long",
|
|
616974
|
+
day: "numeric"
|
|
616975
|
+
}).format(now2);
|
|
616976
|
+
const time = new Intl.DateTimeFormat("en-US", {
|
|
616977
|
+
hour: "numeric",
|
|
616978
|
+
minute: "2-digit",
|
|
616979
|
+
second: "2-digit",
|
|
616980
|
+
timeZoneName: "short"
|
|
616981
|
+
}).format(now2);
|
|
616982
|
+
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env["TZ"] || "system";
|
|
616983
|
+
let diskLine = "";
|
|
616984
|
+
if (repoRoot) {
|
|
616985
|
+
try {
|
|
616986
|
+
const stats = statfsSync7(repoRoot);
|
|
616987
|
+
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
616988
|
+
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
616989
|
+
const usedBytes = totalBytes - freeBytes;
|
|
616990
|
+
const totalGB = Math.round(totalBytes / 1024 ** 3);
|
|
616991
|
+
const freeGB = Math.round(freeBytes / 1024 ** 3);
|
|
616992
|
+
const usedGB = Math.round(usedBytes / 1024 ** 3);
|
|
616993
|
+
const usedPct = totalBytes > 0 ? Math.round(usedBytes / totalBytes * 100) : 0;
|
|
616994
|
+
diskLine = `Disk: disk_available_gb=${freeGB} disk_used_gb=${usedGB} disk_total_gb=${totalGB} disk_used_pct=${usedPct} path=${repoRoot}`;
|
|
616995
|
+
} catch {
|
|
616996
|
+
}
|
|
616997
|
+
}
|
|
616998
|
+
return [
|
|
616999
|
+
`Current date: ${date}`,
|
|
617000
|
+
`Current time: ${time}`,
|
|
617001
|
+
`Current ISO timestamp: ${now2.toISOString()}`,
|
|
617002
|
+
`Timezone: ${timezone}`,
|
|
617003
|
+
repoRoot ? `Working directory: ${repoRoot}` : "",
|
|
617004
|
+
diskLine
|
|
617005
|
+
].filter(Boolean).join("\n");
|
|
617006
|
+
}
|
|
617007
|
+
function quoteConversationBlock(value2, maxChars = 2400) {
|
|
617008
|
+
const text2 = String(value2 ?? "").replace(/\r\n/g, "\n").trim();
|
|
617009
|
+
if (!text2) return "> (empty)";
|
|
617010
|
+
const clipped = text2.length > maxChars ? `${text2.slice(0, Math.max(0, maxChars - 1))}...` : text2;
|
|
617011
|
+
return clipped.split("\n").map((line) => `> ${line}`).join("\n");
|
|
617012
|
+
}
|
|
617013
|
+
function buildScopedConversationMessages(turns, options2) {
|
|
617014
|
+
const pinned = [];
|
|
617015
|
+
const dynamic = [];
|
|
617016
|
+
let latestContextFrame = null;
|
|
617017
|
+
for (const turn of turns) {
|
|
617018
|
+
if (options2.isPinnedSystemTurn(turn) && !pinned.some((p2) => p2.content === turn.content)) {
|
|
617019
|
+
pinned.push(turn);
|
|
617020
|
+
} else if (options2.isContextFrameTurn?.(turn)) {
|
|
617021
|
+
latestContextFrame = turn;
|
|
617022
|
+
} else {
|
|
617023
|
+
dynamic.push(turn);
|
|
617024
|
+
}
|
|
617025
|
+
}
|
|
617026
|
+
if (latestContextFrame) {
|
|
617027
|
+
if (options2.placeContextFrameBeforeLastUser !== false) {
|
|
617028
|
+
let lastUserIdx = -1;
|
|
617029
|
+
for (let i2 = dynamic.length - 1; i2 >= 0; i2--) {
|
|
617030
|
+
if (dynamic[i2].role === "user") {
|
|
617031
|
+
lastUserIdx = i2;
|
|
617032
|
+
break;
|
|
617033
|
+
}
|
|
617034
|
+
}
|
|
617035
|
+
if (lastUserIdx >= 0) dynamic.splice(lastUserIdx, 0, latestContextFrame);
|
|
617036
|
+
else dynamic.push(latestContextFrame);
|
|
617037
|
+
} else {
|
|
617038
|
+
dynamic.push(latestContextFrame);
|
|
617039
|
+
}
|
|
617040
|
+
}
|
|
617041
|
+
const available = Math.max(0, options2.maxMessages - pinned.length);
|
|
617042
|
+
let windowed = dynamic.slice(-available);
|
|
617043
|
+
if (latestContextFrame && available > 0 && !windowed.includes(latestContextFrame)) {
|
|
617044
|
+
windowed = [latestContextFrame, ...windowed.slice(-(available - 1))];
|
|
617045
|
+
}
|
|
617046
|
+
return [...pinned, ...windowed];
|
|
617047
|
+
}
|
|
617048
|
+
function buildVoiceSessionContext(args) {
|
|
617049
|
+
const maxTranscriptTurns = Math.max(1, args.maxTranscriptTurns ?? 8);
|
|
617050
|
+
const voiceLines = (args.voiceTranscript ?? []).slice(-maxTranscriptTurns).map((turn) => `${formatClock(turn.ts)} ${turn.role}: ${singleLine(turn.content, 360)}`);
|
|
617051
|
+
const relayLines = (args.relayTranscript ?? []).slice(-maxTranscriptTurns).map((turn) => {
|
|
617052
|
+
const dir = turn.dir === "toMain" ? "voice->main" : "main->voice";
|
|
617053
|
+
return `${formatClock(turn.ts)} ${dir}: ${singleLine(turn.content, 360)}`;
|
|
617054
|
+
});
|
|
617055
|
+
const taskLine = args.activeTask ? `active=${args.activeTask.active ? "yes" : "no"} tool_calls=${args.activeTask.toolCalls ?? 0} files_touched=${args.activeTask.filesTouched ?? 0}` : "active=unknown";
|
|
617056
|
+
const sections = [
|
|
617057
|
+
`## Runtime Context
|
|
617058
|
+
|
|
617059
|
+
${buildConversationRuntimeContext(/* @__PURE__ */ new Date(), args.repoRoot)}`,
|
|
617060
|
+
[
|
|
617061
|
+
"## Voice/Live Session Contract",
|
|
617062
|
+
"",
|
|
617063
|
+
`surface=voicechat session_id=${args.sessionId} turn=${args.turnCount}`,
|
|
617064
|
+
`main_agent_task=${taskLine}`,
|
|
617065
|
+
"Latest user utterance remains the active request. Earlier ASR transcript turns are conversational history, not new instructions.",
|
|
617066
|
+
"ASR text can be noisy. Prefer consensus-filtered final turns, resolve pronouns from recent context, and ask for clarification rather than filling gaps.",
|
|
617067
|
+
"Live perception is evidence for the current reply, not a topic to narrate unless the user asks about it."
|
|
617068
|
+
].join("\n")
|
|
617069
|
+
];
|
|
617070
|
+
if (voiceLines.length > 0) {
|
|
617071
|
+
sections.push(`## Recent Voice Conversation
|
|
617072
|
+
|
|
617073
|
+
${quoteConversationBlock(voiceLines.join("\n"))}`);
|
|
617074
|
+
}
|
|
617075
|
+
if (relayLines.length > 0) {
|
|
617076
|
+
sections.push(`## Main Agent Relay Stream
|
|
617077
|
+
|
|
617078
|
+
${quoteConversationBlock(relayLines.join("\n"))}`);
|
|
617079
|
+
}
|
|
617080
|
+
if (args.liveContext?.trim()) {
|
|
617081
|
+
sections.push(`## Live Context Frame
|
|
617082
|
+
|
|
617083
|
+
${args.liveContext.trim()}`);
|
|
617084
|
+
}
|
|
617085
|
+
return sections.join("\n\n");
|
|
617086
|
+
}
|
|
617087
|
+
function singleLine(value2, maxChars) {
|
|
617088
|
+
const clean5 = value2.replace(/\s+/g, " ").trim();
|
|
617089
|
+
return clean5.length > maxChars ? `${clean5.slice(0, Math.max(0, maxChars - 1))}...` : clean5;
|
|
617090
|
+
}
|
|
617091
|
+
function formatClock(ts) {
|
|
617092
|
+
try {
|
|
617093
|
+
return new Date(ts).toLocaleTimeString("en-US", {
|
|
617094
|
+
hour: "2-digit",
|
|
617095
|
+
minute: "2-digit",
|
|
617096
|
+
second: "2-digit"
|
|
617097
|
+
});
|
|
617098
|
+
} catch {
|
|
617099
|
+
return "unknown-time";
|
|
617100
|
+
}
|
|
617101
|
+
}
|
|
617102
|
+
var init_conversation_context = __esm({
|
|
617103
|
+
"packages/cli/src/tui/conversation-context.ts"() {
|
|
617104
|
+
"use strict";
|
|
617105
|
+
}
|
|
617106
|
+
});
|
|
617107
|
+
|
|
616967
617108
|
// packages/cli/src/tui/generative-progress.ts
|
|
616968
617109
|
function generationKindForToolName(toolName) {
|
|
616969
617110
|
if (toolName === "generate_image") return "image";
|
|
@@ -628273,7 +628414,7 @@ import { EventEmitter as EventEmitter8 } from "node:events";
|
|
|
628273
628414
|
import { randomBytes as randomBytes22, timingSafeEqual } from "node:crypto";
|
|
628274
628415
|
import { URL as URL2 } from "node:url";
|
|
628275
628416
|
import { loadavg as loadavg2, cpus as cpus4, totalmem as totalmem7, freemem as freemem6 } from "node:os";
|
|
628276
|
-
import { existsSync as existsSync119, readFileSync as readFileSync98, writeFileSync as writeFileSync61, unlinkSync as unlinkSync21, mkdirSync as mkdirSync73, readdirSync as readdirSync39, statSync as statSync47, statfsSync as
|
|
628417
|
+
import { existsSync as existsSync119, readFileSync as readFileSync98, writeFileSync as writeFileSync61, unlinkSync as unlinkSync21, mkdirSync as mkdirSync73, readdirSync as readdirSync39, statSync as statSync47, statfsSync as statfsSync8 } from "node:fs";
|
|
628277
628418
|
import { join as join133 } from "node:path";
|
|
628278
628419
|
function cleanForwardHeaders(raw, targetHost) {
|
|
628279
628420
|
const out = {};
|
|
@@ -628543,7 +628684,7 @@ async function collectSystemMetricsAsync() {
|
|
|
628543
628684
|
utilization: -1
|
|
628544
628685
|
};
|
|
628545
628686
|
try {
|
|
628546
|
-
const fs12 =
|
|
628687
|
+
const fs12 = statfsSync8(process.cwd());
|
|
628547
628688
|
const totalBytes = fs12.blocks * fs12.bsize;
|
|
628548
628689
|
const freeBytes = fs12.bavail * fs12.bsize;
|
|
628549
628690
|
const usedBytes = totalBytes - freeBytes;
|
|
@@ -636157,7 +636298,7 @@ function setTerminalTitle(task, version5) {
|
|
|
636157
636298
|
process.stdout.write(data);
|
|
636158
636299
|
}
|
|
636159
636300
|
}
|
|
636160
|
-
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, BOX_BJ, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, HEADER_BUTTON_LEFT, HEADER_BUTTON_RIGHT, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
|
|
636301
|
+
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, BOX_BJ, BOX_TJ, ENHANCE_SEG_INNER, ENHANCE_SPIN_FRAMES, _globalFooterLock, RESET4, CURSOR_BLINK_BLOCK, _isWindows, HEADER_BUTTON_LEFT, HEADER_BUTTON_RIGHT, SPONSOR_HEADER_LABEL_MAX, _termTitleWriter, StatusBar;
|
|
636161
636302
|
var init_status_bar = __esm({
|
|
636162
636303
|
"packages/cli/src/tui/status-bar.ts"() {
|
|
636163
636304
|
"use strict";
|
|
@@ -636350,6 +636491,20 @@ var init_status_bar = __esm({
|
|
|
636350
636491
|
BOX_H3 = "─";
|
|
636351
636492
|
BOX_V3 = "│";
|
|
636352
636493
|
BOX_BJ = "┴";
|
|
636494
|
+
BOX_TJ = "┬";
|
|
636495
|
+
ENHANCE_SEG_INNER = 11;
|
|
636496
|
+
ENHANCE_SPIN_FRAMES = [
|
|
636497
|
+
"⠋",
|
|
636498
|
+
"⠙",
|
|
636499
|
+
"⠹",
|
|
636500
|
+
"⠸",
|
|
636501
|
+
"⠼",
|
|
636502
|
+
"⠴",
|
|
636503
|
+
"⠦",
|
|
636504
|
+
"⠧",
|
|
636505
|
+
"⠇",
|
|
636506
|
+
"⠏"
|
|
636507
|
+
];
|
|
636353
636508
|
_globalFooterLock = false;
|
|
636354
636509
|
RESET4 = "\x1B[0m";
|
|
636355
636510
|
CURSOR_BLINK_BLOCK = "\x1B[1 q";
|
|
@@ -636519,6 +636674,23 @@ var init_status_bar = __esm({
|
|
|
636519
636674
|
* own output is suppressed.
|
|
636520
636675
|
*/
|
|
636521
636676
|
inputStateProvider = null;
|
|
636677
|
+
// ── Input-box "enhance" prompt-expansion button ──────────────────────
|
|
636678
|
+
/** Mutates the underlying input buffer (line + cursor). Wired to DirectInput.setLine. */
|
|
636679
|
+
_inputMutator = null;
|
|
636680
|
+
/** Runs the inference-based prompt expansion. Returns the enhanced prompt or null. */
|
|
636681
|
+
_enhanceHandler = null;
|
|
636682
|
+
/** Current enhance-button lifecycle state. */
|
|
636683
|
+
_enhanceState = "idle";
|
|
636684
|
+
/** The pre-expansion seed text, restored when the user rejects the expansion. */
|
|
636685
|
+
_enhanceOriginal = null;
|
|
636686
|
+
/** Transient press-flash target for visual click feedback. */
|
|
636687
|
+
_enhancePressed = null;
|
|
636688
|
+
/** Spinner animation frame index while state === "busy". */
|
|
636689
|
+
_enhanceSpinFrame = 0;
|
|
636690
|
+
/** Spinner redraw timer while state === "busy". */
|
|
636691
|
+
_enhanceSpinTimer = null;
|
|
636692
|
+
/** Sub-zones for the accept (✔) / reject (✖) confirm glyphs (confirm state only). */
|
|
636693
|
+
_enhanceConfirmZones = null;
|
|
636522
636694
|
/** Whether microphone is recording (blinking indicator) */
|
|
636523
636695
|
_recording = false;
|
|
636524
636696
|
/** Whether speech is currently detected on the mic (from ListenEngine metering) */
|
|
@@ -638524,6 +638696,7 @@ var init_status_bar = __esm({
|
|
|
638524
638696
|
if (viewId) this.switchToView(viewId);
|
|
638525
638697
|
return;
|
|
638526
638698
|
}
|
|
638699
|
+
if (type === "press" && this.handleFooterInputClick(row, col)) return;
|
|
638527
638700
|
const L = layout();
|
|
638528
638701
|
const inContent = row >= this.scrollRegionTop && row <= L.contentBottom;
|
|
638529
638702
|
if (inContent) {
|
|
@@ -638802,8 +638975,7 @@ var init_status_bar = __esm({
|
|
|
638802
638975
|
for (let row = clearStart; row <= rows; row++) {
|
|
638803
638976
|
buf += `\x1B[${row};1H\x1B[2K`;
|
|
638804
638977
|
}
|
|
638805
|
-
|
|
638806
|
-
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, boxInnerP))}${BOX_TR3}${RESET4}${PANEL_BG_SEQ}`;
|
|
638978
|
+
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}${PANEL_BG_SEQ}`;
|
|
638807
638979
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
638808
638980
|
const row = pos.inputStartRow + 1 + i2;
|
|
638809
638981
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
@@ -638812,7 +638984,12 @@ var init_status_bar = __esm({
|
|
|
638812
638984
|
buf += `${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}`;
|
|
638813
638985
|
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
|
|
638814
638986
|
}
|
|
638815
|
-
buf +=
|
|
638987
|
+
buf += this.buildEnhanceSegment(
|
|
638988
|
+
w,
|
|
638989
|
+
pos.inputStartRow + 1,
|
|
638990
|
+
inputWrap.lines.length
|
|
638991
|
+
);
|
|
638992
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
|
|
638816
638993
|
if (pos.metricsRow > 0) {
|
|
638817
638994
|
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
|
|
638818
638995
|
}
|
|
@@ -640226,9 +640403,268 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640226
640403
|
this._brailleSpinner.setMetrics({ contextPct });
|
|
640227
640404
|
}
|
|
640228
640405
|
/** Compute how many visual lines the current input text occupies */
|
|
640406
|
+
// ── "enhance" segment geometry ───────────────────────────────────────
|
|
640407
|
+
/** Whether the enhance segment is wired and the terminal is wide enough. */
|
|
640408
|
+
enhanceSegEnabled(termWidth) {
|
|
640409
|
+
if (!this._enhanceHandler) return false;
|
|
640410
|
+
const w = termWidth ?? getTermWidth();
|
|
640411
|
+
return w >= this.promptWidth + ENHANCE_SEG_INNER + 16;
|
|
640412
|
+
}
|
|
640413
|
+
/** Column of the │ divider that separates the input area from the button cell. */
|
|
640414
|
+
enhanceDividerCol(termWidth) {
|
|
640415
|
+
const w = termWidth ?? getTermWidth();
|
|
640416
|
+
return w - 1 - ENHANCE_SEG_INNER;
|
|
640417
|
+
}
|
|
640229
640418
|
inputTextWidth(termWidth) {
|
|
640230
640419
|
const w = termWidth ?? getTermWidth();
|
|
640231
|
-
|
|
640420
|
+
const seg = this.enhanceSegEnabled(w) ? ENHANCE_SEG_INNER + 1 : 0;
|
|
640421
|
+
return Math.max(1, w - this.promptWidth - 2 - seg);
|
|
640422
|
+
}
|
|
640423
|
+
/** Box top border with an optional ┬ carving out the enhance segment. */
|
|
640424
|
+
buildInputBoxTop(w) {
|
|
640425
|
+
if (!this.enhanceSegEnabled(w)) {
|
|
640426
|
+
return `${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, w - 2))}${BOX_TR3}${RESET4}`;
|
|
640427
|
+
}
|
|
640428
|
+
const dividerCol = this.enhanceDividerCol(w);
|
|
640429
|
+
const leftDashes = Math.max(0, dividerCol - 2);
|
|
640430
|
+
return `${BOX_FG}${BOX_TL3}${BOX_H3.repeat(leftDashes)}${BOX_TJ}${BOX_H3.repeat(ENHANCE_SEG_INNER)}${BOX_TR3}${RESET4}`;
|
|
640431
|
+
}
|
|
640432
|
+
/** Box bottom border with an optional ┴ closing the enhance segment. */
|
|
640433
|
+
buildInputBoxBottom(w) {
|
|
640434
|
+
if (!this.enhanceSegEnabled(w)) {
|
|
640435
|
+
return `${BOX_FG}${BOX_BL3}${BOX_H3.repeat(Math.max(0, w - 2))}${BOX_BR3}${RESET4}`;
|
|
640436
|
+
}
|
|
640437
|
+
const dividerCol = this.enhanceDividerCol(w);
|
|
640438
|
+
const leftDashes = Math.max(0, dividerCol - 2);
|
|
640439
|
+
return `${BOX_FG}${BOX_BL3}${BOX_H3.repeat(leftDashes)}${BOX_BJ}${BOX_H3.repeat(ENHANCE_SEG_INNER)}${BOX_BR3}${RESET4}`;
|
|
640440
|
+
}
|
|
640441
|
+
/**
|
|
640442
|
+
* Draw the │ divider down each input row plus the enhance/confirm button in
|
|
640443
|
+
* the right-hand cell (button label on the first input row only). Returns an
|
|
640444
|
+
* ANSI overlay string (with CUP moves) that callers append AFTER painting the
|
|
640445
|
+
* input-row content, so it lands on top of the erase-to-EOL fill. Also records
|
|
640446
|
+
* the click zones consumed by handleFooterInputClick().
|
|
640447
|
+
*/
|
|
640448
|
+
buildEnhanceSegment(w, firstInputRow, rowCount) {
|
|
640449
|
+
if (!this.enhanceSegEnabled(w) || rowCount < 1) {
|
|
640450
|
+
this._enhanceConfirmZones = null;
|
|
640451
|
+
return "";
|
|
640452
|
+
}
|
|
640453
|
+
const dividerCol = this.enhanceDividerCol(w);
|
|
640454
|
+
const cellStart = dividerCol + 1;
|
|
640455
|
+
const cellEnd = w - 1;
|
|
640456
|
+
let buf = "";
|
|
640457
|
+
for (let i2 = 0; i2 < rowCount; i2++) {
|
|
640458
|
+
const row = firstInputRow + i2;
|
|
640459
|
+
buf += `\x1B[${row};${dividerCol}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
|
|
640460
|
+
if (i2 > 0) {
|
|
640461
|
+
buf += `\x1B[${row};${cellStart}H${PANEL_BG_SEQ}${" ".repeat(ENHANCE_SEG_INNER)}`;
|
|
640462
|
+
}
|
|
640463
|
+
}
|
|
640464
|
+
buf += this.buildEnhanceButtonCell(firstInputRow, cellStart);
|
|
640465
|
+
void cellEnd;
|
|
640466
|
+
return buf;
|
|
640467
|
+
}
|
|
640468
|
+
/** Render the button-cell content for the current enhance state (width = ENHANCE_SEG_INNER). */
|
|
640469
|
+
buildEnhanceButtonCell(row, cellStart) {
|
|
640470
|
+
const cup = `\x1B[${row};${cellStart}H`;
|
|
640471
|
+
if (this._enhanceState === "busy") {
|
|
640472
|
+
this._enhanceConfirmZones = null;
|
|
640473
|
+
const frame = ENHANCE_SPIN_FRAMES[this._enhanceSpinFrame % ENHANCE_SPIN_FRAMES.length] ?? "⠋";
|
|
640474
|
+
const pad = Math.floor((ENHANCE_SEG_INNER - 1) / 2);
|
|
640475
|
+
const cell = " ".repeat(pad) + frame + " ".repeat(ENHANCE_SEG_INNER - 1 - pad);
|
|
640476
|
+
return `${cup}${PANEL_BG_SEQ}\x1B[38;5;${TEXT_DIM}m${cell}${RESET4}${PANEL_BG_SEQ}`;
|
|
640477
|
+
}
|
|
640478
|
+
if (this._enhanceState === "confirm") {
|
|
640479
|
+
const rejectIdx = 2;
|
|
640480
|
+
const acceptIdx = ENHANCE_SEG_INNER - 3;
|
|
640481
|
+
const rejectPressed = this._enhancePressed === "reject";
|
|
640482
|
+
const acceptPressed = this._enhancePressed === "accept";
|
|
640483
|
+
const rejectFg = rejectPressed ? "\x1B[1;7;38;5;196m" : "\x1B[1;38;5;196m";
|
|
640484
|
+
const acceptFg = acceptPressed ? "\x1B[1;7;38;5;40m" : "\x1B[1;38;5;40m";
|
|
640485
|
+
let out = `${cup}${PANEL_BG_SEQ}`;
|
|
640486
|
+
for (let i2 = 0; i2 < ENHANCE_SEG_INNER; i2++) {
|
|
640487
|
+
if (i2 === rejectIdx) out += `${rejectFg}✖${RESET4}${PANEL_BG_SEQ}`;
|
|
640488
|
+
else if (i2 === acceptIdx) out += `${acceptFg}✔${RESET4}${PANEL_BG_SEQ}`;
|
|
640489
|
+
else out += " ";
|
|
640490
|
+
}
|
|
640491
|
+
this._enhanceConfirmZones = {
|
|
640492
|
+
reject: { c0: cellStart + rejectIdx, c1: cellStart + rejectIdx },
|
|
640493
|
+
accept: { c0: cellStart + acceptIdx, c1: cellStart + acceptIdx }
|
|
640494
|
+
};
|
|
640495
|
+
return out;
|
|
640496
|
+
}
|
|
640497
|
+
this._enhanceConfirmZones = null;
|
|
640498
|
+
const label = "enhance";
|
|
640499
|
+
const totalPad = ENHANCE_SEG_INNER - label.length;
|
|
640500
|
+
const left = Math.floor(totalPad / 2);
|
|
640501
|
+
const chip = " ".repeat(left) + label + " ".repeat(totalPad - left);
|
|
640502
|
+
const pressed = this._enhancePressed === "enhance";
|
|
640503
|
+
const body = pressed ? `\x1B[7m${HEADER_BUTTON_BG}${HEADER_BUTTON_FG}${chip}${RESET4}` : `${HEADER_BUTTON_BG}${HEADER_BUTTON_FG}${chip}${RESET4}`;
|
|
640504
|
+
return `${cup}${body}${PANEL_BG_SEQ}`;
|
|
640505
|
+
}
|
|
640506
|
+
// ── "enhance" public API + lifecycle ─────────────────────────────────
|
|
640507
|
+
/** Wire the buffer mutator (DirectInput.setLine) so clicks can move the cursor / swap text. */
|
|
640508
|
+
setInputMutator(fn) {
|
|
640509
|
+
this._inputMutator = fn;
|
|
640510
|
+
}
|
|
640511
|
+
/**
|
|
640512
|
+
* Wire the inference-backed prompt-expansion handler. Passing a handler also
|
|
640513
|
+
* enables the enhance segment in the input box. `seed` is the current input
|
|
640514
|
+
* text; resolve with the expanded prompt, or null to abort (no change).
|
|
640515
|
+
*/
|
|
640516
|
+
setEnhanceHandler(fn) {
|
|
640517
|
+
this._enhanceHandler = fn;
|
|
640518
|
+
}
|
|
640519
|
+
/** Reset the enhance button to idle (called on submit / escape / new prompt). */
|
|
640520
|
+
resetEnhance() {
|
|
640521
|
+
const wasActive = this._enhanceState !== "idle";
|
|
640522
|
+
this.stopEnhanceSpinner();
|
|
640523
|
+
this._enhanceState = "idle";
|
|
640524
|
+
this._enhanceOriginal = null;
|
|
640525
|
+
this._enhancePressed = null;
|
|
640526
|
+
if (wasActive && this.active && !this._resizing) {
|
|
640527
|
+
this.renderFooterAndPositionInput();
|
|
640528
|
+
}
|
|
640529
|
+
}
|
|
640530
|
+
startEnhanceSpinner() {
|
|
640531
|
+
this.stopEnhanceSpinner();
|
|
640532
|
+
this._enhanceSpinTimer = setInterval(() => {
|
|
640533
|
+
if (this._enhanceState !== "busy") {
|
|
640534
|
+
this.stopEnhanceSpinner();
|
|
640535
|
+
return;
|
|
640536
|
+
}
|
|
640537
|
+
this._enhanceSpinFrame++;
|
|
640538
|
+
if (this.active && !this._resizing && this.writeDepth === 0) {
|
|
640539
|
+
this.renderFooterAndPositionInput();
|
|
640540
|
+
}
|
|
640541
|
+
}, 120);
|
|
640542
|
+
if (typeof this._enhanceSpinTimer.unref === "function") {
|
|
640543
|
+
this._enhanceSpinTimer.unref();
|
|
640544
|
+
}
|
|
640545
|
+
}
|
|
640546
|
+
stopEnhanceSpinner() {
|
|
640547
|
+
if (this._enhanceSpinTimer) {
|
|
640548
|
+
clearInterval(this._enhanceSpinTimer);
|
|
640549
|
+
this._enhanceSpinTimer = null;
|
|
640550
|
+
}
|
|
640551
|
+
}
|
|
640552
|
+
/** Kick off the expansion inference for the current input text. */
|
|
640553
|
+
beginEnhance() {
|
|
640554
|
+
if (this._enhanceState !== "idle" || !this._enhanceHandler) return;
|
|
640555
|
+
const state = this.inputStateProvider?.();
|
|
640556
|
+
const original = state?.line ?? "";
|
|
640557
|
+
const seed = original.trim();
|
|
640558
|
+
if (!seed) return;
|
|
640559
|
+
this._enhanceOriginal = original;
|
|
640560
|
+
this._enhanceState = "busy";
|
|
640561
|
+
this._enhanceSpinFrame = 0;
|
|
640562
|
+
this._enhancePressed = null;
|
|
640563
|
+
this.startEnhanceSpinner();
|
|
640564
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640565
|
+
const handler = this._enhanceHandler;
|
|
640566
|
+
void (async () => {
|
|
640567
|
+
let expanded = null;
|
|
640568
|
+
try {
|
|
640569
|
+
expanded = await handler(seed);
|
|
640570
|
+
} catch {
|
|
640571
|
+
expanded = null;
|
|
640572
|
+
}
|
|
640573
|
+
this.stopEnhanceSpinner();
|
|
640574
|
+
if (this._enhanceState !== "busy") {
|
|
640575
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640576
|
+
return;
|
|
640577
|
+
}
|
|
640578
|
+
const clean5 = (expanded ?? "").trim();
|
|
640579
|
+
if (clean5 && clean5 !== seed) {
|
|
640580
|
+
this._inputMutator?.(clean5, clean5.length);
|
|
640581
|
+
this._enhanceState = "confirm";
|
|
640582
|
+
} else {
|
|
640583
|
+
this._enhanceState = "idle";
|
|
640584
|
+
this._enhanceOriginal = null;
|
|
640585
|
+
}
|
|
640586
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640587
|
+
})();
|
|
640588
|
+
}
|
|
640589
|
+
/** Resolve the confirm state: accept keeps the expansion, reject restores the seed. */
|
|
640590
|
+
resolveEnhance(accept) {
|
|
640591
|
+
if (this._enhanceState !== "confirm") return;
|
|
640592
|
+
if (!accept && this._enhanceOriginal != null) {
|
|
640593
|
+
const orig = this._enhanceOriginal;
|
|
640594
|
+
this._inputMutator?.(orig, orig.length);
|
|
640595
|
+
}
|
|
640596
|
+
this._enhanceState = "idle";
|
|
640597
|
+
this._enhanceOriginal = null;
|
|
640598
|
+
this._enhancePressed = null;
|
|
640599
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640600
|
+
}
|
|
640601
|
+
/** Brief press-flash for click feedback, then repaint. */
|
|
640602
|
+
flashEnhancePress(which3) {
|
|
640603
|
+
this._enhancePressed = which3;
|
|
640604
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640605
|
+
setTimeout(() => {
|
|
640606
|
+
if (this._enhancePressed === which3) {
|
|
640607
|
+
this._enhancePressed = null;
|
|
640608
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640609
|
+
}
|
|
640610
|
+
}, 130);
|
|
640611
|
+
}
|
|
640612
|
+
/**
|
|
640613
|
+
* Handle a press inside the footer input box: the enhance/confirm button,
|
|
640614
|
+
* or a click in the text area to reposition the cursor. Returns true when the
|
|
640615
|
+
* click was consumed.
|
|
640616
|
+
*/
|
|
640617
|
+
handleFooterInputClick(row, col) {
|
|
640618
|
+
if (!this.inputStateProvider) return false;
|
|
640619
|
+
const w = getTermWidth();
|
|
640620
|
+
const pos = this.rowPositions(termRows());
|
|
640621
|
+
const inputLines = this.computeInputLineCount(w);
|
|
640622
|
+
const firstInputRow = pos.inputStartRow + 1;
|
|
640623
|
+
const lastInputRow = firstInputRow + inputLines - 1;
|
|
640624
|
+
if (row < firstInputRow || row > lastInputRow) return false;
|
|
640625
|
+
if (this.enhanceSegEnabled(w)) {
|
|
640626
|
+
const dividerCol = this.enhanceDividerCol(w);
|
|
640627
|
+
const cellStart = dividerCol + 1;
|
|
640628
|
+
const cellEnd = w - 1;
|
|
640629
|
+
if (col >= dividerCol && col <= cellEnd) {
|
|
640630
|
+
if (this._enhanceState === "confirm") {
|
|
640631
|
+
const mid = Math.floor((cellStart + cellEnd) / 2);
|
|
640632
|
+
if (col <= mid) {
|
|
640633
|
+
this.flashEnhancePress("reject");
|
|
640634
|
+
this.resolveEnhance(false);
|
|
640635
|
+
} else {
|
|
640636
|
+
this.flashEnhancePress("accept");
|
|
640637
|
+
this.resolveEnhance(true);
|
|
640638
|
+
}
|
|
640639
|
+
return true;
|
|
640640
|
+
}
|
|
640641
|
+
if (this._enhanceState === "idle") {
|
|
640642
|
+
this.flashEnhancePress("enhance");
|
|
640643
|
+
this.beginEnhance();
|
|
640644
|
+
return true;
|
|
640645
|
+
}
|
|
640646
|
+
return true;
|
|
640647
|
+
}
|
|
640648
|
+
if (col >= dividerCol) return false;
|
|
640649
|
+
}
|
|
640650
|
+
const availWidth = this.inputTextWidth(w);
|
|
640651
|
+
const line = this.inputStateProvider().line ?? "";
|
|
640652
|
+
const { rawLines, charPositions } = this.wrapPlainInputText(
|
|
640653
|
+
line,
|
|
640654
|
+
availWidth
|
|
640655
|
+
);
|
|
640656
|
+
const lineIdx = Math.min(
|
|
640657
|
+
Math.max(0, row - firstInputRow),
|
|
640658
|
+
rawLines.length - 1
|
|
640659
|
+
);
|
|
640660
|
+
const rawLine = rawLines[lineIdx] ?? "";
|
|
640661
|
+
let charInLine = col - this.promptWidth - 2;
|
|
640662
|
+
if (charInLine < 0) charInLine = 0;
|
|
640663
|
+
if (charInLine > rawLine.length) charInLine = rawLine.length;
|
|
640664
|
+
const newCursor = (charPositions[lineIdx] ?? 0) + charInLine;
|
|
640665
|
+
this._inputMutator?.(line, Math.min(newCursor, line.length));
|
|
640666
|
+
if (this.active && !this._resizing) this.renderFooterAndPositionInput();
|
|
640667
|
+
return true;
|
|
640232
640668
|
}
|
|
640233
640669
|
wrapPlainInputText(text2, availWidth) {
|
|
640234
640670
|
const width = Math.max(1, availWidth);
|
|
@@ -640462,8 +640898,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640462
640898
|
}
|
|
640463
640899
|
const inputWrap = this.wrapInput(w);
|
|
640464
640900
|
let buf = "\x1B[?7l";
|
|
640465
|
-
|
|
640466
|
-
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, boxInner))}${BOX_TR3}${RESET4}${PANEL_BG_SEQ}`;
|
|
640901
|
+
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}${PANEL_BG_SEQ}`;
|
|
640467
640902
|
const Lspacer = layout();
|
|
640468
640903
|
const spacerRow = pos.inputStartRow - 1;
|
|
640469
640904
|
const tasksOccupiesSpacer = Lspacer.tasksHeight > 0 && spacerRow >= Lspacer.tasksTop && spacerRow <= Lspacer.tasksBottom;
|
|
@@ -640479,6 +640914,11 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640479
640914
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
640480
640915
|
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
|
|
640481
640916
|
}
|
|
640917
|
+
buf += this.buildEnhanceSegment(
|
|
640918
|
+
w,
|
|
640919
|
+
pos.inputStartRow + 1,
|
|
640920
|
+
inputWrap.lines.length
|
|
640921
|
+
);
|
|
640482
640922
|
const cursorTermRow = pos.inputStartRow + 1 + inputWrap.cursorRow;
|
|
640483
640923
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
640484
640924
|
for (let si = 0; si < this._suggestions.length; si++) {
|
|
@@ -640495,9 +640935,9 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640495
640935
|
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
|
|
640496
640936
|
}
|
|
640497
640937
|
const suggestBottomRow = pos.suggestStartRow + this._suggestions.length;
|
|
640498
|
-
buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
640938
|
+
buf += `\x1B[${suggestBottomRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
|
|
640499
640939
|
} else {
|
|
640500
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
640940
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
|
|
640501
640941
|
}
|
|
640502
640942
|
if (pos.metricsRow > 0) {
|
|
640503
640943
|
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
|
|
@@ -640537,7 +640977,6 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640537
640977
|
if (pos.tabBarRow > 0) {
|
|
640538
640978
|
buf += `\x1B[${pos.tabBarRow};1H${PANEL_BG_SEQ}\x1B[2K${RESET4}`;
|
|
640539
640979
|
}
|
|
640540
|
-
const boxInnerR = w - 2;
|
|
640541
640980
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
640542
640981
|
for (let si = 0; si < this._suggestions.length; si++) {
|
|
640543
640982
|
const row = pos.suggestStartRow + si;
|
|
@@ -640548,9 +640987,9 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640548
640987
|
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ} ${marker}\x1B[38;5;${TEXT_DIM}m/${fg2}${cmd}`;
|
|
640549
640988
|
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}`;
|
|
640550
640989
|
}
|
|
640551
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
640990
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
|
|
640552
640991
|
} else {
|
|
640553
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
640992
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
|
|
640554
640993
|
}
|
|
640555
640994
|
if (pos.metricsRow > 0) {
|
|
640556
640995
|
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
|
|
@@ -640604,14 +641043,18 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640604
641043
|
}
|
|
640605
641044
|
}
|
|
640606
641045
|
buf += "\x1B[?7l";
|
|
640607
|
-
|
|
640608
|
-
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, boxInnerH))}${BOX_TR3}${RESET4}`;
|
|
641046
|
+
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}`;
|
|
640609
641047
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
640610
641048
|
const row = pos.inputStartRow + 1 + i2;
|
|
640611
641049
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
640612
641050
|
const lineContent = `${prefix}${inputWrap.lines[i2]}`;
|
|
640613
641051
|
buf += `\x1B[${row};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}${lineContent}${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}`;
|
|
640614
641052
|
}
|
|
641053
|
+
buf += this.buildEnhanceSegment(
|
|
641054
|
+
w,
|
|
641055
|
+
pos.inputStartRow + 1,
|
|
641056
|
+
inputWrap.lines.length
|
|
641057
|
+
);
|
|
640615
641058
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
640616
641059
|
for (let si = 0; si < this._suggestions.length; si++) {
|
|
640617
641060
|
const row = pos.suggestStartRow + si;
|
|
@@ -640625,8 +641068,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640625
641068
|
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}`;
|
|
640626
641069
|
}
|
|
640627
641070
|
}
|
|
640628
|
-
|
|
640629
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_BL3}${BOX_H3.repeat(Math.max(0, boxInnerS))}${BOX_BR3}${RESET4}`;
|
|
641071
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}`;
|
|
640630
641072
|
if (pos.metricsRow > 0) {
|
|
640631
641073
|
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}`;
|
|
640632
641074
|
}
|
|
@@ -640643,8 +641085,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640643
641085
|
if (heightDelta !== 0) this.refreshTasksPanelAfterLayoutChange();
|
|
640644
641086
|
} else {
|
|
640645
641087
|
let buf = "\x1B7\x1B[?25l\x1B[?7l";
|
|
640646
|
-
|
|
640647
|
-
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${BOX_FG}${BOX_TL3}${BOX_H3.repeat(Math.max(0, boxInnerH))}${BOX_TR3}${RESET4}${PANEL_BG_SEQ}`;
|
|
641088
|
+
buf += `\x1B[${pos.inputStartRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxTop(w)}${PANEL_BG_SEQ}`;
|
|
640648
641089
|
for (let i2 = 0; i2 < inputWrap.lines.length; i2++) {
|
|
640649
641090
|
const row = pos.inputStartRow + 1 + i2;
|
|
640650
641091
|
const prefix = i2 === 0 ? this.promptText : " ".repeat(this.promptWidth);
|
|
@@ -640654,6 +641095,11 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640654
641095
|
buf += `${PANEL_BG_SEQ}\x1B[K`;
|
|
640655
641096
|
buf += `\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
|
|
640656
641097
|
}
|
|
641098
|
+
buf += this.buildEnhanceSegment(
|
|
641099
|
+
w,
|
|
641100
|
+
pos.inputStartRow + 1,
|
|
641101
|
+
inputWrap.lines.length
|
|
641102
|
+
);
|
|
640657
641103
|
if (this._suggestions.length > 0 && pos.suggestStartRow > 0) {
|
|
640658
641104
|
for (let si = 0; si < this._suggestions.length; si++) {
|
|
640659
641105
|
const row = pos.suggestStartRow + si;
|
|
@@ -640667,7 +641113,7 @@ ${CONTENT_BG_SEQ}`);
|
|
|
640667
641113
|
buf += `${PANEL_BG_SEQ}\x1B[K\x1B[${row};${w}H${BOX_FG}${BOX_V3}${RESET4}${PANEL_BG_SEQ}`;
|
|
640668
641114
|
}
|
|
640669
641115
|
}
|
|
640670
|
-
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${
|
|
641116
|
+
buf += `\x1B[${pos.bufferRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildInputBoxBottom(w)}${PANEL_BG_SEQ}`;
|
|
640671
641117
|
if (pos.metricsRow > 0) {
|
|
640672
641118
|
buf += `\x1B[${pos.metricsRow};1H${PANEL_BG_SEQ}\x1B[2K${this.buildMetricsLine()}${RESET4}${PANEL_BG_SEQ}`;
|
|
640673
641119
|
}
|
|
@@ -684006,147 +684452,6 @@ var init_emotion_engine = __esm({
|
|
|
684006
684452
|
}
|
|
684007
684453
|
});
|
|
684008
684454
|
|
|
684009
|
-
// packages/cli/src/tui/conversation-context.ts
|
|
684010
|
-
import { statfsSync as statfsSync8 } from "node:fs";
|
|
684011
|
-
function buildConversationRuntimeContext(now2 = /* @__PURE__ */ new Date(), repoRoot) {
|
|
684012
|
-
const date = new Intl.DateTimeFormat("en-US", {
|
|
684013
|
-
weekday: "long",
|
|
684014
|
-
year: "numeric",
|
|
684015
|
-
month: "long",
|
|
684016
|
-
day: "numeric"
|
|
684017
|
-
}).format(now2);
|
|
684018
|
-
const time = new Intl.DateTimeFormat("en-US", {
|
|
684019
|
-
hour: "numeric",
|
|
684020
|
-
minute: "2-digit",
|
|
684021
|
-
second: "2-digit",
|
|
684022
|
-
timeZoneName: "short"
|
|
684023
|
-
}).format(now2);
|
|
684024
|
-
const timezone = Intl.DateTimeFormat().resolvedOptions().timeZone || process.env["TZ"] || "system";
|
|
684025
|
-
let diskLine = "";
|
|
684026
|
-
if (repoRoot) {
|
|
684027
|
-
try {
|
|
684028
|
-
const stats = statfsSync8(repoRoot);
|
|
684029
|
-
const totalBytes = Number(stats.blocks) * Number(stats.bsize);
|
|
684030
|
-
const freeBytes = Number(stats.bavail) * Number(stats.bsize);
|
|
684031
|
-
const usedBytes = totalBytes - freeBytes;
|
|
684032
|
-
const totalGB = Math.round(totalBytes / 1024 ** 3);
|
|
684033
|
-
const freeGB = Math.round(freeBytes / 1024 ** 3);
|
|
684034
|
-
const usedGB = Math.round(usedBytes / 1024 ** 3);
|
|
684035
|
-
const usedPct = totalBytes > 0 ? Math.round(usedBytes / totalBytes * 100) : 0;
|
|
684036
|
-
diskLine = `Disk: disk_available_gb=${freeGB} disk_used_gb=${usedGB} disk_total_gb=${totalGB} disk_used_pct=${usedPct} path=${repoRoot}`;
|
|
684037
|
-
} catch {
|
|
684038
|
-
}
|
|
684039
|
-
}
|
|
684040
|
-
return [
|
|
684041
|
-
`Current date: ${date}`,
|
|
684042
|
-
`Current time: ${time}`,
|
|
684043
|
-
`Current ISO timestamp: ${now2.toISOString()}`,
|
|
684044
|
-
`Timezone: ${timezone}`,
|
|
684045
|
-
repoRoot ? `Working directory: ${repoRoot}` : "",
|
|
684046
|
-
diskLine
|
|
684047
|
-
].filter(Boolean).join("\n");
|
|
684048
|
-
}
|
|
684049
|
-
function quoteConversationBlock(value2, maxChars = 2400) {
|
|
684050
|
-
const text2 = String(value2 ?? "").replace(/\r\n/g, "\n").trim();
|
|
684051
|
-
if (!text2) return "> (empty)";
|
|
684052
|
-
const clipped = text2.length > maxChars ? `${text2.slice(0, Math.max(0, maxChars - 1))}...` : text2;
|
|
684053
|
-
return clipped.split("\n").map((line) => `> ${line}`).join("\n");
|
|
684054
|
-
}
|
|
684055
|
-
function buildScopedConversationMessages(turns, options2) {
|
|
684056
|
-
const pinned = [];
|
|
684057
|
-
const dynamic = [];
|
|
684058
|
-
let latestContextFrame = null;
|
|
684059
|
-
for (const turn of turns) {
|
|
684060
|
-
if (options2.isPinnedSystemTurn(turn) && !pinned.some((p2) => p2.content === turn.content)) {
|
|
684061
|
-
pinned.push(turn);
|
|
684062
|
-
} else if (options2.isContextFrameTurn?.(turn)) {
|
|
684063
|
-
latestContextFrame = turn;
|
|
684064
|
-
} else {
|
|
684065
|
-
dynamic.push(turn);
|
|
684066
|
-
}
|
|
684067
|
-
}
|
|
684068
|
-
if (latestContextFrame) {
|
|
684069
|
-
if (options2.placeContextFrameBeforeLastUser !== false) {
|
|
684070
|
-
let lastUserIdx = -1;
|
|
684071
|
-
for (let i2 = dynamic.length - 1; i2 >= 0; i2--) {
|
|
684072
|
-
if (dynamic[i2].role === "user") {
|
|
684073
|
-
lastUserIdx = i2;
|
|
684074
|
-
break;
|
|
684075
|
-
}
|
|
684076
|
-
}
|
|
684077
|
-
if (lastUserIdx >= 0) dynamic.splice(lastUserIdx, 0, latestContextFrame);
|
|
684078
|
-
else dynamic.push(latestContextFrame);
|
|
684079
|
-
} else {
|
|
684080
|
-
dynamic.push(latestContextFrame);
|
|
684081
|
-
}
|
|
684082
|
-
}
|
|
684083
|
-
const available = Math.max(0, options2.maxMessages - pinned.length);
|
|
684084
|
-
let windowed = dynamic.slice(-available);
|
|
684085
|
-
if (latestContextFrame && available > 0 && !windowed.includes(latestContextFrame)) {
|
|
684086
|
-
windowed = [latestContextFrame, ...windowed.slice(-(available - 1))];
|
|
684087
|
-
}
|
|
684088
|
-
return [...pinned, ...windowed];
|
|
684089
|
-
}
|
|
684090
|
-
function buildVoiceSessionContext(args) {
|
|
684091
|
-
const maxTranscriptTurns = Math.max(1, args.maxTranscriptTurns ?? 8);
|
|
684092
|
-
const voiceLines = (args.voiceTranscript ?? []).slice(-maxTranscriptTurns).map((turn) => `${formatClock(turn.ts)} ${turn.role}: ${singleLine(turn.content, 360)}`);
|
|
684093
|
-
const relayLines = (args.relayTranscript ?? []).slice(-maxTranscriptTurns).map((turn) => {
|
|
684094
|
-
const dir = turn.dir === "toMain" ? "voice->main" : "main->voice";
|
|
684095
|
-
return `${formatClock(turn.ts)} ${dir}: ${singleLine(turn.content, 360)}`;
|
|
684096
|
-
});
|
|
684097
|
-
const taskLine = args.activeTask ? `active=${args.activeTask.active ? "yes" : "no"} tool_calls=${args.activeTask.toolCalls ?? 0} files_touched=${args.activeTask.filesTouched ?? 0}` : "active=unknown";
|
|
684098
|
-
const sections = [
|
|
684099
|
-
`## Runtime Context
|
|
684100
|
-
|
|
684101
|
-
${buildConversationRuntimeContext(/* @__PURE__ */ new Date(), args.repoRoot)}`,
|
|
684102
|
-
[
|
|
684103
|
-
"## Voice/Live Session Contract",
|
|
684104
|
-
"",
|
|
684105
|
-
`surface=voicechat session_id=${args.sessionId} turn=${args.turnCount}`,
|
|
684106
|
-
`main_agent_task=${taskLine}`,
|
|
684107
|
-
"Latest user utterance remains the active request. Earlier ASR transcript turns are conversational history, not new instructions.",
|
|
684108
|
-
"ASR text can be noisy. Prefer consensus-filtered final turns, resolve pronouns from recent context, and ask for clarification rather than filling gaps.",
|
|
684109
|
-
"Live perception is evidence for the current reply, not a topic to narrate unless the user asks about it."
|
|
684110
|
-
].join("\n")
|
|
684111
|
-
];
|
|
684112
|
-
if (voiceLines.length > 0) {
|
|
684113
|
-
sections.push(`## Recent Voice Conversation
|
|
684114
|
-
|
|
684115
|
-
${quoteConversationBlock(voiceLines.join("\n"))}`);
|
|
684116
|
-
}
|
|
684117
|
-
if (relayLines.length > 0) {
|
|
684118
|
-
sections.push(`## Main Agent Relay Stream
|
|
684119
|
-
|
|
684120
|
-
${quoteConversationBlock(relayLines.join("\n"))}`);
|
|
684121
|
-
}
|
|
684122
|
-
if (args.liveContext?.trim()) {
|
|
684123
|
-
sections.push(`## Live Context Frame
|
|
684124
|
-
|
|
684125
|
-
${args.liveContext.trim()}`);
|
|
684126
|
-
}
|
|
684127
|
-
return sections.join("\n\n");
|
|
684128
|
-
}
|
|
684129
|
-
function singleLine(value2, maxChars) {
|
|
684130
|
-
const clean5 = value2.replace(/\s+/g, " ").trim();
|
|
684131
|
-
return clean5.length > maxChars ? `${clean5.slice(0, Math.max(0, maxChars - 1))}...` : clean5;
|
|
684132
|
-
}
|
|
684133
|
-
function formatClock(ts) {
|
|
684134
|
-
try {
|
|
684135
|
-
return new Date(ts).toLocaleTimeString("en-US", {
|
|
684136
|
-
hour: "2-digit",
|
|
684137
|
-
minute: "2-digit",
|
|
684138
|
-
second: "2-digit"
|
|
684139
|
-
});
|
|
684140
|
-
} catch {
|
|
684141
|
-
return "unknown-time";
|
|
684142
|
-
}
|
|
684143
|
-
}
|
|
684144
|
-
var init_conversation_context = __esm({
|
|
684145
|
-
"packages/cli/src/tui/conversation-context.ts"() {
|
|
684146
|
-
"use strict";
|
|
684147
|
-
}
|
|
684148
|
-
});
|
|
684149
|
-
|
|
684150
684455
|
// packages/cli/src/tui/telegram-format.ts
|
|
684151
684456
|
function escapeHtml2(text2) {
|
|
684152
684457
|
return String(text2 ?? "").replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
@@ -745080,6 +745385,118 @@ When done, either call task_complete with your answer, or use FINAL_VAR(variable
|
|
|
745080
745385
|
}
|
|
745081
745386
|
};
|
|
745082
745387
|
}
|
|
745388
|
+
function extractEnhancedPrompt(raw) {
|
|
745389
|
+
const text2 = raw.trim();
|
|
745390
|
+
if (!text2) return null;
|
|
745391
|
+
const tryParse = (candidate) => {
|
|
745392
|
+
try {
|
|
745393
|
+
const obj = JSON.parse(candidate);
|
|
745394
|
+
const v = obj["enhancedPrompt"] ?? obj["enhanced_prompt"] ?? obj["prompt"] ?? obj["result"];
|
|
745395
|
+
return typeof v === "string" && v.trim() ? v : null;
|
|
745396
|
+
} catch {
|
|
745397
|
+
return null;
|
|
745398
|
+
}
|
|
745399
|
+
};
|
|
745400
|
+
const direct = tryParse(text2);
|
|
745401
|
+
if (direct) return direct;
|
|
745402
|
+
const fenced = text2.match(/```(?:json)?\s*([\s\S]*?)```/i);
|
|
745403
|
+
if (fenced?.[1]) {
|
|
745404
|
+
const f2 = tryParse(fenced[1].trim());
|
|
745405
|
+
if (f2) return f2;
|
|
745406
|
+
}
|
|
745407
|
+
const brace = text2.match(/\{[\s\S]*\}/);
|
|
745408
|
+
if (brace?.[0]) {
|
|
745409
|
+
const b = tryParse(brace[0]);
|
|
745410
|
+
if (b) return b;
|
|
745411
|
+
}
|
|
745412
|
+
const keyed = text2.match(
|
|
745413
|
+
/"enhanced_?[Pp]rompt"\s*:\s*"((?:[^"\\]|\\.)*)"/
|
|
745414
|
+
);
|
|
745415
|
+
if (keyed?.[1]) {
|
|
745416
|
+
try {
|
|
745417
|
+
return JSON.parse('"' + keyed[1] + '"');
|
|
745418
|
+
} catch {
|
|
745419
|
+
return keyed[1];
|
|
745420
|
+
}
|
|
745421
|
+
}
|
|
745422
|
+
if (!text2.startsWith("{") && !text2.startsWith("[")) return text2;
|
|
745423
|
+
return null;
|
|
745424
|
+
}
|
|
745425
|
+
async function enhancePromptViaInference(seed, ctx3) {
|
|
745426
|
+
const seedText = seed.trim();
|
|
745427
|
+
if (!seedText) return null;
|
|
745428
|
+
let backend;
|
|
745429
|
+
try {
|
|
745430
|
+
if (ctx3.config.backendType === "nexus") {
|
|
745431
|
+
const nexusTool = new NexusTool(ctx3.repoRoot);
|
|
745432
|
+
const peer = ctx3.config.backendUrl.startsWith("peer://") ? ctx3.config.backendUrl.slice(7) : void 0;
|
|
745433
|
+
backend = new NexusAgenticBackend(
|
|
745434
|
+
nexusTool.sendCommand.bind(nexusTool),
|
|
745435
|
+
ctx3.config.model,
|
|
745436
|
+
peer,
|
|
745437
|
+
ctx3.config.apiKey
|
|
745438
|
+
);
|
|
745439
|
+
} else {
|
|
745440
|
+
backend = new OllamaAgenticBackend(
|
|
745441
|
+
ctx3.config.backendUrl,
|
|
745442
|
+
ctx3.config.model,
|
|
745443
|
+
ctx3.config.apiKey
|
|
745444
|
+
);
|
|
745445
|
+
}
|
|
745446
|
+
} catch {
|
|
745447
|
+
return null;
|
|
745448
|
+
}
|
|
745449
|
+
const recent = ctx3.recentHistory.filter((h) => h && h.trim()).slice(0, 5).map((h, i2) => ` ${i2 + 1}. ${h.trim().slice(0, 240)}`).join("\n");
|
|
745450
|
+
let runtimeCtx = "";
|
|
745451
|
+
try {
|
|
745452
|
+
runtimeCtx = buildConversationRuntimeContext(/* @__PURE__ */ new Date(), ctx3.repoRoot);
|
|
745453
|
+
} catch {
|
|
745454
|
+
runtimeCtx = "";
|
|
745455
|
+
}
|
|
745456
|
+
const userPrompt = [
|
|
745457
|
+
"Expand the SEED PROMPT below into a comprehensive, precise, self-contained instruction set for an agentic coding assistant.",
|
|
745458
|
+
"Preserve the user's original intent exactly. Do NOT answer or solve it, do NOT invent unrelated scope.",
|
|
745459
|
+
"Clarify the goal, surface implied requirements, relevant constraints, edge cases, and concrete acceptance criteria.",
|
|
745460
|
+
"Fold in only the session context that is actually relevant. Keep it phrased as an instruction in the user's voice.",
|
|
745461
|
+
"Return no preamble and no meta-commentary about the prompt itself.",
|
|
745462
|
+
ctx3.activeGoal ? `
|
|
745463
|
+
Task currently in progress: ${ctx3.activeGoal.slice(0, 400)}` : "",
|
|
745464
|
+
recent ? `
|
|
745465
|
+
Recent prompts this session (newest first):
|
|
745466
|
+
${recent}` : "",
|
|
745467
|
+
runtimeCtx ? `
|
|
745468
|
+
Session/runtime context:
|
|
745469
|
+
${runtimeCtx}` : "",
|
|
745470
|
+
`
|
|
745471
|
+
SEED PROMPT:
|
|
745472
|
+
${seedText}`
|
|
745473
|
+
].filter(Boolean).join("\n");
|
|
745474
|
+
try {
|
|
745475
|
+
const resp = await backend.chatCompletion({
|
|
745476
|
+
messages: [
|
|
745477
|
+
{
|
|
745478
|
+
role: "system",
|
|
745479
|
+
content: `You are a prompt-expansion engine. You rewrite a user's short seed prompt into a richer, unambiguous instruction that fully captures their intent. Return strict JSON only: {"enhancedPrompt": string}.`
|
|
745480
|
+
},
|
|
745481
|
+
{ role: "user", content: userPrompt }
|
|
745482
|
+
],
|
|
745483
|
+
tools: [],
|
|
745484
|
+
temperature: 0.4,
|
|
745485
|
+
maxTokens: 1400,
|
|
745486
|
+
timeoutMs: 6e4,
|
|
745487
|
+
think: false,
|
|
745488
|
+
responseFormat: { type: "json_object" }
|
|
745489
|
+
});
|
|
745490
|
+
const rawContent2 = resp.choices?.[0]?.message?.content ?? "";
|
|
745491
|
+
if (!rawContent2) return null;
|
|
745492
|
+
const enhanced = extractEnhancedPrompt(rawContent2);
|
|
745493
|
+
if (!enhanced) return null;
|
|
745494
|
+
const clean5 = enhanced.trim();
|
|
745495
|
+
return clean5 && clean5 !== seedText ? clean5 : null;
|
|
745496
|
+
} catch {
|
|
745497
|
+
return null;
|
|
745498
|
+
}
|
|
745499
|
+
}
|
|
745083
745500
|
async function startInteractive(config, repoPath2) {
|
|
745084
745501
|
const repoRoot = resolve74(repoPath2 ?? cwd());
|
|
745085
745502
|
try {
|
|
@@ -746664,6 +747081,20 @@ This is an independent background session started from /background.`
|
|
|
746664
747081
|
}
|
|
746665
747082
|
})();
|
|
746666
747083
|
});
|
|
747084
|
+
statusBar.setInputMutator((line, cursor) => {
|
|
747085
|
+
try {
|
|
747086
|
+
rl.setLine(line, cursor);
|
|
747087
|
+
} catch {
|
|
747088
|
+
}
|
|
747089
|
+
});
|
|
747090
|
+
statusBar.setEnhanceHandler(async (seedPrompt) => {
|
|
747091
|
+
return enhancePromptViaInference(seedPrompt, {
|
|
747092
|
+
config: currentConfig,
|
|
747093
|
+
repoRoot,
|
|
747094
|
+
recentHistory: savedHistory,
|
|
747095
|
+
activeGoal: activeTask ? lastSubmittedPrompt : void 0
|
|
747096
|
+
});
|
|
747097
|
+
});
|
|
746667
747098
|
if (process.stdin.isTTY && typeof process.stdin.setRawMode === "function") {
|
|
746668
747099
|
process.stdin.setRawMode(true);
|
|
746669
747100
|
}
|
|
@@ -750180,6 +750611,7 @@ ${result.content.slice(0, 2e3)}${result.content.length > 2e3 ? "\n[truncated]" :
|
|
|
750180
750611
|
};
|
|
750181
750612
|
};
|
|
750182
750613
|
rl.on("line", (line) => {
|
|
750614
|
+
statusBar.resetEnhance?.();
|
|
750183
750615
|
if (!setupReady) return;
|
|
750184
750616
|
idleMemoryMaintenance?.notifyActivity();
|
|
750185
750617
|
persistHistoryLine(line);
|
|
@@ -751172,6 +751604,7 @@ ${c3.dim("(Use /quit to exit)")}
|
|
|
751172
751604
|
showPrompt();
|
|
751173
751605
|
});
|
|
751174
751606
|
_escapeHandler = () => {
|
|
751607
|
+
statusBar.resetEnhance?.();
|
|
751175
751608
|
if (!activeTask && statusBar.activeViewId !== "main") {
|
|
751176
751609
|
statusBar.switchToView("main");
|
|
751177
751610
|
statusBar.beginContentWrite();
|
|
@@ -751682,6 +752115,7 @@ var init_interactive = __esm({
|
|
|
751682
752115
|
init_memory_paths();
|
|
751683
752116
|
init_visual_sensor_guidance();
|
|
751684
752117
|
init_live_sensors();
|
|
752118
|
+
init_conversation_context();
|
|
751685
752119
|
init_dist8();
|
|
751686
752120
|
init_dist8();
|
|
751687
752121
|
init_dist8();
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omnius",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.489",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omnius",
|
|
9
|
-
"version": "1.0.
|
|
9
|
+
"version": "1.0.489",
|
|
10
10
|
"bundleDependencies": [
|
|
11
11
|
"image-to-ascii"
|
|
12
12
|
],
|
package/package.json
CHANGED